C# 使用实体框架初始化数据
我想在应用程序运行之前初始化数据库中的虚拟数据。我有一个SQL脚本,可以将数据直接插入到表中 问题是,当我要更新元素时,会出现以下异常: EntityFramework.dll中的“System.InvalidOperationException”en EntityFramework.dll:附加类型为“Es.Udc.DotNet.MiniPortal.Model.Book”的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。 这是我的更新方法:C# 使用实体框架初始化数据,c#,entity-framework,C#,Entity Framework,我想在应用程序运行之前初始化数据库中的虚拟数据。我有一个SQL脚本,可以将数据直接插入到表中 问题是,当我要更新元素时,会出现以下异常: EntityFramework.dll中的“System.InvalidOperationException”en EntityFramework.dll:附加类型为“Es.Udc.DotNet.MiniPortal.Model.Book”的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或
public void Update(E entity)
{
dbContext.Entry<E>(entity).State = EntityState.Modified;
dbContext.SaveChanges();
}
公共作废更新(E实体)
{
dbContext.Entry(entity.State=EntityState.Modified;
dbContext.SaveChanges();
}
我认为这是因为EF不跟踪项目,但我不知道我能做什么。初始化虚拟数据并由EF跟踪的最佳方法是什么?谢谢。我建议您在将实体发送到更新方法之前进行选择(使用EF),然后在将实体设置为修改后尝试将其附加到上下文(这取决于您是否使用changetraking选项)
dbContext.Set().Attach(实体);
例如,这是我的存储库更新方法(仅举一个例子):
public void更新(TEntity更新,Tkey)
{
updated.ObjectState=ObjectState.Modified;
var existing=_dbSet.Find(键);
if(existing==null)返回;
existing.ObjectState=ObjectState.Modified;
dbContext.Entry(现有).CurrentValues.SetValues(更新);
dbContext.Set().Attach(现有);
}
我认为这是因为EF不跟踪项目
这是因为EF正在跟踪实体。使用相同的DbContext实例,您试图通过实体的不同实例读取和更新实体。实体通过引用进行跟踪
这意味着传递给此Update()
方法的实体与从数据库中读取的实体不同
如果您没有在代码中明确执行此操作,则可能是代码经过映射阶段,其中要更新的实体是新的(明确地或通过反射),并从另一个实体填充,例如通过AutoMapper映射的viewmodel
另一种情况是上下文的生存期太长,例如,因为它是从静态变量和/或单例或配置不正确的依赖项注入容器中使用的
因此,要么:
- 修复DbContext的生存期,以便在上下文的不同实例上进行查找和更新
- 如果必须在与更新相同的DbContext实例上进行查找,请确保更新从第一次查找返回的实体
- 在查找时。多次查询同一实体可能有意义,在这种情况下,在某些位置使用非跟踪实体可能是解决方案
无论您选择哪种方法,都需要处理并发性,这是您不想自己处理的 尝试使用EF选择一个“可能在之前”选项。。类似于var query=db。Book.ToList()你能在尝试修改数据时发布一些代码(C#)吗?嗨@federicoscamuzzi我用代码编辑了答案,但我无法编辑,因为这是老师给的库
dbContext.Set<TEntity>().Attach(entity);
public void Update(TEntity updated, Tkey key)
{
updated.ObjectState = ObjectState.Modified;
var existing = _dbSet.Find(key);
if (existing == null) return;
existing.ObjectState = ObjectState.Modified;
dbContext.Entry(existing).CurrentValues.SetValues(updated);
dbContext.Set<TEntity>().Attach(existing);
}