我在Asp.net中遇到实体框架问题。每当将对象添加到数据库时,我都想获取Id值。我怎样才能做到这一点?
SaveChanges
为了获得ID而立即打电话。在这里进一步阅读。
我在Asp.net中遇到实体框架问题。每当将对象添加到数据库时,我都想获取Id值。我怎样才能做到这一点?
SaveChanges
为了获得ID而立即打电话。在这里进一步阅读。
Answers:
这很容易。如果您正在使用DB生成的ID(如IDENTITY
在MS SQL),你只需要实体添加ObjectSet
和SaveChanges
有关ObjectContext
。Id
将自动为您填充:
using (var context = new MyContext())
{
context.MyEntities.Add(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Yes it's here
}
默认情况下,实体框架遵循各INSERT
用SELECT SCOPE_IDENTITY()
时自动生成的Id
用于秒。
在使用实体框架时,我一直在使用Ladislav Mrnka的答案来成功检索ID,但是我在这里发布是因为我一直在滥用它(即在不需要它的地方使用它),并认为我会将我的发现发布在这里-案例中的人们希望“解决”我遇到的问题。
考虑与客户具有外键关系的Order对象。当我同时添加一个新客户和一个新订单时,我正在执行以下操作:
var customer = new Customer(); //no Id yet;
var order = new Order(); //requires Customer.Id to link it to customer;
context.Customers.Add(customer);
context.SaveChanges();//this generates the Id for customer
order.CustomerId = customer.Id;//finally I can set the Id
但是在我的情况下,这不是必需的,因为我在customer.Id和order.CustomerId之间具有外键关系
我要做的就是这个。
var customer = new Customer(); //no Id yet;
var order = new Order{Customer = customer};
context.SaveChanges();//adds customer.Id to customer and the correct CustomerId to order
现在,当我保存更改时,还将为客户生成的ID添加到订单中。我不需要其他步骤
我知道这并不能回答最初的问题,但我认为这可能会帮助EF新手开发人员避免过度使用票房最高的答案来解决不必要的问题。
这也意味着更新可以在单个事务中完成,从而避免使用Orphin数据(要么完成更新,要么不更新)。
保存更改后,您需要重新加载实体。因为它已被数据库触发器更改,但EF无法跟踪该触发器。因此,我们需要再次从数据库重新加载实体,
db.Entry(MyNewObject).GetDatabaseValues();
然后
int id = myNewObject.Id;
看看下面问题中的@jayantha答案:
使用defaultValue时,如何获取实体框架中插入的实体的ID?
在下面的问题中查找@christian答案也可能有帮助:
.GetDatabaseValues();
如果您只是将模型保存到数据库中,则不必这样做。该ID应自动重新填充到模型中。
GetDatabaseValues()
,如果它不知道对象在数据库中查找的ID?
请参考此链接。
http://www.ladislavmrnka.com/2011/03/the-bug-in-storegenicpattern-fixed-in-vs-2010-sp1/
您必须将StoreGeneratedPattern的属性设置为identity,然后尝试自己的代码。
否则您也可以使用它。
using (var context = new MyContext())
{
context.MyEntities.AddObject(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Your Identity column ID
}
StoreGeneratedPattern
是我缺少的一块。
您只能在保存后获取ID,而可以在保存之前创建新的Guid并进行分配。
我遇到一种情况,我需要在数据库中插入数据,同时需要使用实体框架来获取主ID。解决方案:
long id;
IGenericQueryRepository<myentityclass, Entityname> InfoBase = null;
try
{
InfoBase = new GenericQueryRepository<myentityclass, Entityname>();
InfoBase.Add(generalinfo);
InfoBase.Context.SaveChanges();
id = entityclassobj.ID;
return id;
}
所有答案都非常适合他们自己的情况,我所做的不同是我直接从Add()返回给这样的int变量的对象(TEntity)分配了int PK。
using (Entities entities = new Entities())
{
int employeeId = entities.Employee.Add(new Employee
{
EmployeeName = employeeComplexModel.EmployeeName,
EmployeeCreatedDate = DateTime.Now,
EmployeeUpdatedDate = DateTime.Now,
EmployeeStatus = true
}).EmployeeId;
//...use id for other work
}
因此,您无需创建整个新对象,而只需执行所需的操作即可:)
编辑@GertArnold先生:
Add
(如果是DbSet.Add
)并不能奇迹般地分配一个值EmployeeId
。
SaveChanges
。不可能。除非您有其他分配过程,EmployeeId
例如在Employee
的构造函数中。或者您使用处于EF核心ForSqlServerUseSequenceHiLo
。无论如何,您并没有给出全部图片。
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;
这将起作用。
Repository
。而“这将起作用”是一些解释!
有两种策略:
使用数据库生成的ID
(int
或GUID
)
缺点:
您应该执行SaveChanges()
以获得ID
刚刚保存的实体的。
优点:
可以使用int
身份。
使用客户端生成 ID
-仅GUID。
优点:缩小 SaveChanges
操作量。能够在每个操作中插入一个新对象的大图。
缺点:
只允许 GUID
第一次使用EF 6.x代码时
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
并初始化数据库表,它将放置一个
(newsequentialid())
在表头中的“默认值”或“绑定”下,允许在插入ID时填充ID。
问题是,如果您创建表并添加
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
稍后,将来的更新数据库将不会重新添加(newsequentialid())
修复正确的方法是擦除迁移,删除数据库并重新迁移...,也可以只将(newsequentialid())添加到表设计器中。
when -column- is NULL, then NEWID()