正确添加多行,但不更新(C#,实体框架6)

正确添加多行,但不更新(C#,实体框架6),c#,sql,linq,entity-framework-6,crud,C#,Sql,Linq,Entity Framework 6,Crud,正如您在下面看到的,我正在尝试更新“活动”和“版本”字段,它们是templateData对象的属性 当我想添加新记录时,它工作良好,满足了需要。但当我尝试更新state.modified行时,错误是: 附加类型为“…”的实体失败,因为另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,并且没有收到数据库生成的键值。在这种情况下,使用“添加”方法

正如您在下面看到的,我正在尝试更新“活动”和“版本”字段,它们是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

非常感谢您的及时和翔实的回答。