是否可以强制 DbContext.MyTable.Local 成员在 DbContext.SaveChanges() 执行之前分配自动 ID? (EFCore + SQLite)
Posted
技术标签:
【中文标题】是否可以强制 DbContext.MyTable.Local 成员在 DbContext.SaveChanges() 执行之前分配自动 ID? (EFCore + SQLite)【英文标题】:Is it possible to enforce DbContext.MyTable.Local members to have auto ID assigned before DbContext.SaveChanges() execution? (EFCore + SQLite) 【发布时间】:2020-03-03 17:41:41 【问题描述】:所以我在实际保存之前尝试访问我的本地(或者您可以称之为“临时/运行时/RAM”)数据库(使用带有 EF Core 的 SQLite)它在硬盘上。发现我可以使用DbContext.MyTable.Local
访问本地myTable
,但问题是尚未分配ID
的自动增量。那么我可以强制我的本地表成员在执行DbContext.SaveChanges()
之前自动分配ID
吗?如果没有,还有什么办法?
这是我的代码:
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");
【问题讨论】:
您能否详细说明您要完成的工作,以及为什么在保存记录后获取 ID 为时已晚? 我试图让用户操作他的本地数据库并仅通过“保存到数据库”按钮将更改保存到实际数据库中。 为时已晚,因为我在保存到实际数据库之前将值(包括 ID)放在本地数据库中 我不确定您的特定用例,但您应该能够创建一个界面,用户可以在其中操作对象列表,然后将其保存到数据库中完毕。我不确定为什么在将 ID 保存到数据库之前需要分配 ID。 【参考方案1】:在 EF 中,如果模型具有 ID
属性作为 int,它应该自动将其设置为 PK 和自动增量,除非您另有指定。如果问题只是“我可以在不保存到数据库的情况下获得自动生成的 ID”吗?答案是否定的,你不能。
为了获取自动生成的 ID 列的 ID,您必须先将更改保存到数据库。之后,将设置新记录的ID
属性。
MyClass newClass = new MyClass()
Name = "MyName",
Amount = 10
;
_myDbContext.MyClasses.Add(newClass);
_myDbContext.SaveChanges();
//newClass.ID will be set here.
如果您使用的是自动生成的列,这是唯一的方法。如果您想自己设置 ID - 比如使用 uuid - 您可以对 ID 列进行更改。对于涉及将 ID 列的类型更改为字符串的 uuid,您需要将 MaxLength
设置为您选择使用的任何长度。
class MyClass
[MaxLength(50)]
public string ID get; set;
public string Name get; set;
public int Amount get; set;
然后您可以在写入数据库更改之前手动分配 ID。
还有,在这一行
_myDbContext.MyClasses.ToList(); // forcing to have all members in "_myDbContext.MyClasses.Local". Otherwise only changed/added etc. members appear.
我不确定我是否理解您的逻辑,但是没有理由这样做只是为了将新记录保存到数据库中,并且随着数据库的增长,这样做会大大降低您的应用程序的速度。就目前而言,您正在请求表中每个项目的列表,但您甚至没有将其保存到变量中,因此这一行无非是为了减慢您的程序。
【讨论】:
所以,我需要保存数据库以获取 ID 值...我试图让用户操作他的本地数据库并通过“保存到数据库”按钮将更改保存到实际数据库。在你提到的最后一行代码中:如果我不放那一行,那么我的“MyTable.Local”成员只是我添加/更改的成员,其他未更改的成员没有显示。在调试模块 VS2019 上说:“扩展结果视图将枚举 IEnumerable”所以我相信通过调用 .ToList() 方法读取所有成员以某种方式将所有成员签名为“已更改”(或类似的东西),这样我就可以看到所有成员以上是关于是否可以强制 DbContext.MyTable.Local 成员在 DbContext.SaveChanges() 执行之前分配自动 ID? (EFCore + SQLite)的主要内容,如果未能解决你的问题,请参考以下文章
来自 MYSQL 中某个范围的 Entity Framework Core 随机记录