Можно ли принудить членов DbContext.MyTable.Local иметь автоматический идентификатор, назначенный до выполнения DbContext.SaveChanges ()? (EFCore + SQLite) - PullRequest
0 голосов
/ 03 марта 2020

Итак, я пытался получить доступ к своей локальной (или вы можете назвать ее «временной / рабочей / оперативной памятью») базе данных (используя SQLite с EF Core) перед тем, как сохранить ее на жесткий диск. Обнаружил, что я могу получить доступ к локальному myTable с помощью DbContext.MyTable.Local, но проблема в том, что автоматическое увеличение для ID еще не было назначено. Так можно ли принудительно назначить членам локальной таблицы автоматическое назначение ID перед выполнением DbContext.SaveChanges()? Если нет, то какова альтернатива?

Вот мои коды:

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
    }
}

Моя модель:

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

Мой 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 голосов
/ 03 марта 2020

В EF, если модель имеет свойство ID как int, ей следует автоматически установить для него PK и автоинкремент, если не указано иное. Если вопрос просто «могу ли я получить автоматически сгенерированный идентификатор без сохранения в БД», ответ - нет, вы не можете.

Чтобы получить идентификатор для автоматически сгенерированного столбца идентификаторов, вы сначала необходимо сохранить изменения в базе данных. После этого будет установлено свойство ID новой записи.

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

//newClass.ID will be set here. 

Если вы используете автоматически сгенерированный столбец, это единственный способ сделать это. Если вы хотите установить идентификатор самостоятельно - например, с помощью uuid - вы можете внести это изменение в столбец идентификатора. В случае использования uuid, которое может включать изменение типа столбца ID на строку, и вы захотите установить MaxLength на любую длину, которую вы выбираете использовать.

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

Затем вы можете вручную назначить идентификатор перед записью изменений в БД.

Кроме того, в этой строке

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

Я не уверен, что понимаю вашу логику c здесь, но нет причин делать это просто для сохранения новой записи в базе данных. и это резко замедлит работу вашего приложения по мере роста базы данных. В существующем состоянии вы запрашиваете список каждого элемента в таблице, но даже не сохраняете его в переменную, поэтому эта строка ничего не делает, кроме как для замедления вашей программы.

...