In-Memory Database Doesn't Save Data

In-memory database doesn't save data

Your code has multiple serious problems, let's go through them.

  1. services.AddDbContext adds a Scoped service, meaning that instances will be created and disposed on each request. services.AddSingleton adds a Singleton service, so only a single instance will ever be created. You cannot add a scoped service to a singleton one, because the reference the singleton service uses will be disposed and you will end up with a disposed context.

  2. This code:

     return provider.GetService<IUnitOfWork>();

represents the service locator anti-pattern. As you can guess, an anti-pattern is something you want to avoid. I also don't know why you would want a service to build the entire DI container nor why you would want a service to have the responsibility of getting the dependencies it needs itself.


  1. This part here is where your question actually comes from:

     Database.SaveAsync();

You are calling an asynchronous function and not awaiting for it to finish. The task may finish or not, it may throw an error or not, you will never know what happened.

The best thing is that all of these could be avoided if people stopped attempting to create a Unit of Work + Repository pattern over yet another Unit of Work and Repository. Entity Framework Core already implements these:

DbContext => Unit of Work
DbSet => Repository (generic)

Why do you want yet another abstraction? Will you really ever throw away EF Core from the project to justify the maintenance cost of your code?

The entire question code could have just been this:

[Route("api/[controller]")]
public class ItemsController : Controller
{
private readonly YourContext _context;

public ItemsController(YourContext context)
{
_context = context;
}

[HttpPost]
public async Task<IActionResult> Add([FromBody]Item item)
{
context.Items.Add(item);
await context.SaveChangesAsync();

return Ok(item.Id);
}

[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
var item = await context.Items.FindAsync(id);
context.Items.Remove(item);
await context.SaveChangesAsync();

return Ok();
}

[HttpPut]
public async Task<IActionResult> Put([FromBody]Item item)
{
context.Items.Update(item);
await context.SaveChangesAsync();

return Ok();
}
}

Storage: database vs in-memory objects vs in-memory database

If this is nothing but a school assignment or toy project with very simple models and access patterns, then sure rolling your own data persistence might make sense.

However, I'd advocate for using a database if:

  • you have a lot of objects or different types of objects
  • you need to query or filter objects by various criteria
  • you need more reliable data persistence
  • you need multiple services to access the same data
  • you need access controls
  • you need any other database feature

Since you ask about speed, for trivial stuff, in-memory objects will likely be faster to access. But, for more complicated stuff (lots of data, object relations, pagination, etc.), a database could start being faster.

You mention in-memory databases but those would only be used if you want the database features without the persistence and would be closer to your in-memory objects but without the file writing. So it just depends on if you care about keeping the data or not.

Also if you haven't ever worked with any kind of database, now's a perfect time to learn :).

EF Core Seeding mechanism doesn't insert data

The HasData method only configures the entity to have seed data.

To actually seed the Database you need to call

Database.EnsureCreated();

Note that this only applies if the databases doesn't already exist (as In-Memory DB's) since EnsureCreated does nothing otherwise.

For an existing database you need to create and apply migrations.

For reference: Data Seeding

How to save in-memory sqlite database to a file in perl?

Yes, you can use $dbh->sqlite_backup_to_file( $filename ) and then connect to that file like a normal SQLite database. For more see the SQLite Backup API docs.

But you can accomplish basically the same thing with the same performance by turning off AutoCommit and only committing your transaction when you're done with your bulk inserts. SQLite will probably hold all your inserts in memory until they're committed.

my $dbh = DBI->connect(
"dbi:SQLite:dbname=test.sqlite", undef, undef, { RaiseError => 1, AutoCommit => 0 }
);

...do your inserts...

$dbh->commit;

A simple benchmark shows this is just as fast and it's more flexible.

Turning off AutoCommit will give you a big boost with either option.



Related Topics



Leave a reply



Submit