none
Code First - know if entity instance exist into the context RRS feed

  • Question

  • Hi

    I need to change state to related entities, but I am having the following error:

    AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges

    I am using

    context.Entry(instanceEntity).State = EntityState.Unchanged

    but when the instanceEntity already exists into the context I have the error

    how I know if the instanceEntity exist into the context ? if exist I need to assign the Unchanged state

    greetings


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina


    Monday, September 9, 2013 1:12 PM

Answers

  • Hi,

    With the code, I notice that after instanting the user1, there will be three company type entities.

    However, the companydefault entity has the same key with one entity in the List companies.

    The problem is that those two company objects are different objects. When you attach both to your last context (by setting the State) the exception occurs because they are two different objects with the same key.

    There is a blogs shows how to solve the issue below:

    http://blogs.msdn.com/b/diego/archive/2010/10/06/self-tracking-entities-applychanges-and-duplicate-entities.aspx

    And I recommend that we can designer the company entity like:

    class Company
        {
            public int CompanyId { get; set; }
            public bool IdDefault { get; set; }
        }

    Then we can define which is default instanting the user1 like:

    ser user1 = new User()
                {
                    Name = "nombre",
                    Companies = new List<Company>() {
                new Company() { CompanyId = 10,IsDefault=true},
                new Company() { CompanyId = 12,IsDefault=false}
               }
                };
    Regards.

    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Tuesday, September 10, 2013 10:19 AM
    Moderator

All replies

  • Hello,

    With your description, you want to know if the instance Entity exists into the context.

    If I misunderstand you, please let me know.

    In my opinion, we can query EF's ChangeTracker, it's especially well supported with DbContext where you have access to the context cache via the DbSet<T>.Local collection.

    Please have a look at the sample below:

    using (InheritanceMappingContext db = new InheritanceMappingContext())
                {
                    //db.Database.Create();
                    //Insert(db);
                    BillingDetail bd = new BillingDetail() { BillingDetailId = 0, Number = "10001", Owner = "BMX" };
                    BankAccount ba = new BankAccount() { BillingDetailId = 1, BankName = "BankName001", Swift = "Swift001" };
                    CreditCard cc = new CreditCard() { BillingDetailId = 2, CardType = 2, ExpiryMonth = "09", ExpiryYear = "2013" };
                    db.BillingDetails.Add(bd);
                    db.BankAccounts.Add(ba);
                    db.CreditCards.Add(cc);
                    var result = db.Set<BillingDetail>().Local.Where(b => b.BillingDetailId == 0);
                    db.SaveChanges();
                    result = db.Set<BillingDetail>().Local.Where(b => b.BillingDetailId == 0);
                }

    In the sample, the result will find the BillingDetail entity whose BillingDetailId = 0 before inserting into the database.

    Or we should only need to save new values using this:

    1. ObjectContext API: context.YourEntitySet.ApplyCurrentValues(newEntity);
    2. DbContext API: context.Entry(oldEntity).CurrentValues.SetValues(newEntity);

    Best Regards.


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Tuesday, September 10, 2013 2:32 AM
    Moderator
  • Hi

    thanks for your answer

    I try to acces to where() in the Local property, but this is a IList and haven't the where() extension

    The problem is somewhat more generic, I am develop a repository and insert relate entities with many to many relation

    I have the entities

    public class User{
    
        public int UserId { get; set; }
    
        public string Name { get; set; }
    
        public virtual ICollection<Company> Companies{ get; set; }
    
        public virtual Company CompanyDefault { get; set; }
    
    }

    when I create the relation using object instance

    User user1 = new User1(){ Name = "nombre", CompanyDefault = new Company() { CompanyId = 10 }, Companies = new List<Company> () { new Company() { CompanyId = 10 }, new Company() { CompanyId = 12 } } }

    repository.Insert(user1,
    new List<string>() { "CompanyDefault", "Companies" });



    in the respository  define:

            public virtual void Insert(T entity, List<string> unchangeProp = null)
            {
                using (NovedadesCapatazContext context = new NovedadesCapatazContext())
                {
                    context.Entry<T>(entity).State = EntityState.Added;
    
                    if (unchangeProp != null)
                    {
                        foreach (string property in unchangeProp)
                        {
                            PropertyInfo propertyInfo = typeof(T).GetProperty(property);
                            var value = propertyInfo.GetValue(entity, null);
    
    
                            if (propertyInfo.PropertyType.IsGenericType && typeof(ICollection<>).IsAssignableFrom(propertyInfo.PropertyType.GetGenericTypeDefinition()))
                            {
                                ICollection item = (ICollection)value;
                                if (item != null)
                                {
                                    foreach (object o in item)
                                    {
                                        context.Entry(o).State = EntityState.Unchanged;
                                    }
                                }
                            }
                            else
                                context.Entry(value).State = EntityState.Unchanged;
                        }
                    }
    
                    context.SaveChanges();
                }
            }

    I need to assign State = Unchange to CompanyDefault and Companies properties because this already exists and I don't want create the companies again

    the problem is when the same company is asigned into the Entry()

    greetings


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    Tuesday, September 10, 2013 4:37 AM
  • Hi,

    With the code, I notice that after instanting the user1, there will be three company type entities.

    However, the companydefault entity has the same key with one entity in the List companies.

    The problem is that those two company objects are different objects. When you attach both to your last context (by setting the State) the exception occurs because they are two different objects with the same key.

    There is a blogs shows how to solve the issue below:

    http://blogs.msdn.com/b/diego/archive/2010/10/06/self-tracking-entities-applychanges-and-duplicate-entities.aspx

    And I recommend that we can designer the company entity like:

    class Company
        {
            public int CompanyId { get; set; }
            public bool IdDefault { get; set; }
        }

    Then we can define which is default instanting the user1 like:

    ser user1 = new User()
                {
                    Name = "nombre",
                    Companies = new List<Company>() {
                new Company() { CompanyId = 10,IsDefault=true},
                new Company() { CompanyId = 12,IsDefault=false}
               }
                };
    Regards.

    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Tuesday, September 10, 2013 10:19 AM
    Moderator