1

As you can see below, I'm trying to update the "active" and "version" fields, which are properties of the templateData object.

When I want to add a new record, it works fine and meets the needs. But when I try to update the state.modified line, the error is:

Attaching an entity of type '...' failed because another entity already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

Although I have tried many ways of crashing (as you noticed) I have not been successful.

What is the cause of this error? And how can I handle it?

Thank you for your help.

Service:

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;
    }

Entity:

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; }
}

DataContextExtension:

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;
    }

1 Answer 1

1

The problem is that the line

var listTempDatas = _context.TemplateDatas.Where(td => td.TemplateRID == oTemplateData.TemplateRID)
    .ToList();

already loads (tracks) in the context the existing entity you are trying to update.

So first you can try to find it in that list (instead of with a separate database query):

var oldTempData = listTempDatas.FirstOrDefault(td => td.ID == oTemplateData.ID);

and then simply update the properties of the existing entity rather than trying to mark the detached entity as modified:

if (oldTempData != null)
    _context.Entry(oldTempData).CurrentValues.SetValues(oTemplateData); // and there you go
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much for your prompt and informative answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.