正确添加多行,但不更新(C#,实体框架6)
正如您在下面看到的,我正在尝试更新“活动”和“版本”字段,它们是templateData对象的属性 当我想添加新记录时,它工作良好,满足了需要。但当我尝试更新state.modified行时,错误是: 附加类型为“…”的实体失败,因为另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,并且没有收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改” 虽然我尝试过很多方法(正如你所注意到的),但我并没有成功 此错误的原因是什么?我如何处理它? 谢谢你的帮助 服务:正确添加多行,但不更新(C#,实体框架6),c#,sql,linq,entity-framework-6,crud,C#,Sql,Linq,Entity Framework 6,Crud,正如您在下面看到的,我正在尝试更新“活动”和“版本”字段,它们是templateData对象的属性 当我想添加新记录时,它工作良好,满足了需要。但当我尝试更新state.modified行时,错误是: 附加类型为“…”的实体失败,因为另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,并且没有收到数据库生成的键值。在这种情况下,使用“添加”方法
public ResultObject<TemplateData> SaveTemplateData(TemplateData oTemplateData)
{
var oResult = new ResultObject<TemplateData>();
using (var contextTransaction = _context.Database.BeginTransaction())
{
try
{
var listTempDatas = _context.TemplateDatas.Where(td => td.TemplateRID == oTemplateData.TemplateRID)
.ToList();
#region active/version
oTemplateData.Active = true;
if (listTempDatas.Count > 0)
{
#region resetActives
listTempDatas.ForEach(ltd => ltd.Active = false);
#endregion
#region getMaxVersion
var maxVersionValue = listTempDatas.Max(ltd => ltd.TemplateVersion);
//var maxVersionValue2 = listTempDatas.OrderByDescending(ltd => ltd.TemplateVersion).Select(ltd => ltd.TemplateVersion).First();
oTemplateData.TemplateVersion = maxVersionValue + 1;
#endregion
}
else if (listTempDatas.Count == 0)
{
oTemplateData.TemplateVersion = 1;
}
#endregion
if (oTemplateData.ID > 0)
{
var oldTempData = _context.TemplateDatas.AsNoTracking()
.FirstOrDefault(td => td.ID == oTemplateData.ID);
if (oldTempData != null)
_context.Entry(oTemplateData).State = EntityState.Modified;// and there it is
}
else if (oTemplateData.ID == 0)
{
_context.Entry(oTemplateData).State = EntityState.Added;
}
_context.SaveChanges();
oResult.ResulObject = oTemplateData;
contextTransaction.Commit();
}
catch (Exception e)
{
contextTransaction.Rollback();
oResult.AddError("TemplateService.SaveTemplateData", e.ToString());
}
}
return oResult;
}
public class TemplateData
{
...
public int ID { get; set; }
public int? TemplateRID { get; set; }
...
public int? TemplateVersion { get; set; }
public bool? Active { get; set; }
...
public virtual Template Template { get; set; }
}
public static ApplicationDbContext BulkInsert<T>(this ApplicationDbContext context, T entity, int count,
int batchSize) where T : class
{
context.Set<T>().Add(entity);
if (count % batchSize == 0)
{
context.SaveChanges();
context.Dispose();
context = new ApplicationDbContext();
// This is optional
context.Configuration.AutoDetectChangesEnabled = false;
}
return context;
}
DataContextExtension:
public ResultObject<TemplateData> SaveTemplateData(TemplateData oTemplateData)
{
var oResult = new ResultObject<TemplateData>();
using (var contextTransaction = _context.Database.BeginTransaction())
{
try
{
var listTempDatas = _context.TemplateDatas.Where(td => td.TemplateRID == oTemplateData.TemplateRID)
.ToList();
#region active/version
oTemplateData.Active = true;
if (listTempDatas.Count > 0)
{
#region resetActives
listTempDatas.ForEach(ltd => ltd.Active = false);
#endregion
#region getMaxVersion
var maxVersionValue = listTempDatas.Max(ltd => ltd.TemplateVersion);
//var maxVersionValue2 = listTempDatas.OrderByDescending(ltd => ltd.TemplateVersion).Select(ltd => ltd.TemplateVersion).First();
oTemplateData.TemplateVersion = maxVersionValue + 1;
#endregion
}
else if (listTempDatas.Count == 0)
{
oTemplateData.TemplateVersion = 1;
}
#endregion
if (oTemplateData.ID > 0)
{
var oldTempData = _context.TemplateDatas.AsNoTracking()
.FirstOrDefault(td => td.ID == oTemplateData.ID);
if (oldTempData != null)
_context.Entry(oTemplateData).State = EntityState.Modified;// and there it is
}
else if (oTemplateData.ID == 0)
{
_context.Entry(oTemplateData).State = EntityState.Added;
}
_context.SaveChanges();
oResult.ResulObject = oTemplateData;
contextTransaction.Commit();
}
catch (Exception e)
{
contextTransaction.Rollback();
oResult.AddError("TemplateService.SaveTemplateData", e.ToString());
}
}
return oResult;
}
public class TemplateData
{
...
public int ID { get; set; }
public int? TemplateRID { get; set; }
...
public int? TemplateVersion { get; set; }
public bool? Active { get; set; }
...
public virtual Template Template { get; set; }
}
public static ApplicationDbContext BulkInsert<T>(this ApplicationDbContext context, T entity, int count,
int batchSize) where T : class
{
context.Set<T>().Add(entity);
if (count % batchSize == 0)
{
context.SaveChanges();
context.Dispose();
context = new ApplicationDbContext();
// This is optional
context.Configuration.AutoDetectChangesEnabled = false;
}
return context;
}
public static ApplicationDbContext BulkInsert(此ApplicationDbContext上下文,T实体,int计数,
int batchSize),其中T:class
{
context.Set().Add(实体);
如果(计数%batchSize==0)
{
SaveChanges();
context.Dispose();
context=新的ApplicationDbContext();
//这是可选的
context.Configuration.AutoDetectChangesEnabled=false;
}
返回上下文;
}
问题是线路
var listTempDatas = _context.TemplateDatas.Where(td => td.TemplateRID == oTemplateData.TemplateRID)
.ToList();
已在上下文中加载(跟踪)要更新的现有实体
因此,首先您可以尝试在该列表中查找它(而不是使用单独的数据库查询):
然后简单地更新现有实体的属性,而不是尝试将分离的实体标记为已修改:
if (oldTempData != null)
_context.Entry(oldTempData).CurrentValues.SetValues(oTemplateData); // and there you go
非常感谢您的及时和翔实的回答。