Is it possible to enforce DbContext.MyTable.Local members to have auto ID assigned before DbContext.SaveChanges() execution? (EFCore + SQLite)

.net entity-framework-core orm rdbms sqlite

Question

So I was trying to access my local (or you may call it "temporary/runtime/RAM") database (using SQLite with EF Core) before actually saving it on hard-drive. Found out that I can access to local myTable with DbContext.MyTable.Local but the problem is the auto-increment for ID was not assigned yet. So can I enforce my local table members to have auto-assigned ID before executing DbContext.SaveChanges()? If not, what is the alternative?

Here's my codes:

using System.Linq;

class Program
{
    private static MyDbContext _myDbContext = new MyDbContext();

    static void Main(string[] args)
    {
        MyClass newClass = new MyClass() { Name = "MyName", Amount = 10 };
        _myDbContext.MyClasses.ToList();    // forcing to have all members in "_myDbContext.MyClasses.Local". Otherwise only changed/added etc. members appear.
        _myDbContext.MyClasses.Add(newClass);

        int myNewID = newClass.ID; 
        // I need newClass.ID that has been auto-assigned here, but it's currently integer default so myNewID value is 0

        _myDbContext.SaveChanges();
        int myNewerId = newClass.ID;
        // now have new auto-assigned newClass.ID value but It's too late
    }
}

My model:

class MyClass
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Amount { get; set; }
}

My DbContext:

using Microsoft.EntityFrameworkCore;

class MyDbContext : DbContext
{
    public DbSet<MyClass> MyClasses { get; set; }

    private static bool _created = false;
    public MyDbContext()
    {
        if (!_created)
        {
            _created = true;
            //Database.EnsureDeleted();
            Database.EnsureCreated();
        }
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionbuilder)
    {
        optionbuilder.UseSqlite(@"Data Source=..\TestDB.db");
    }
}
1
0
3/3/2020 5:41:41 PM

Popular Answer

In EF, if a model has an ID property as an int, it should automatically set it to PK and auto-increment, unless you specify otherwise. If the question is simply "can I obtain an auto-generated ID without saving to the DB," the answer is no, you cannot.

In order to get the ID for an auto-generated ID column, you must save the changes to the database first. After that, the new record's ID property will be set.

MyClass newClass = new MyClass() { 
  Name = "MyName", 
  Amount = 10 
};
_myDbContext.MyClasses.Add(newClass);
_myDbContext.SaveChanges();

//newClass.ID will be set here. 

If you're using an auto-generated column, this is just the only way to do it. If you want to set the ID yourself - like using a uuid - you could make that change to the ID column. In the case of a uuid that would involve changing the type of the ID column to string, and you'll want to set a MaxLength to whatever the length of the thing you choose to use.

class MyClass
{
    [MaxLength(50)]
    public string ID { get; set; }
    public string Name { get; set; }
    public int Amount { get; set; }
}

Then you can manually assign the ID before the DB changes have been written.

Also, in this line

_myDbContext.MyClasses.ToList();    // forcing to have all members in "_myDbContext.MyClasses.Local". Otherwise only changed/added etc. members appear.

I'm not sure I understand your logic here, but there's no reason to do this just to save a new record to the database, and doing so will drastically slow down your application as your database grows. As it stands, you're requesting a list of every item in the table, but you're not even saving it to a variable, so this line is doing nothing more than to slow down your program.

0
3/3/2020 6:07:56 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow