none
Code First - Assign state to related entities RRS feed

  • Question

  • Hi

    I have two entities related

    public class WorkReport
    {
    	public int WorkReportID { get; set; }
    	public string Description { get; set; }
    
    	public int? CoordinateID { get; set; }
    	public Coordinate Coordinate { get; set; }
    
    }
        
    public class Coordinate
    {
    	public int CoordinateID { get; set; }
    
    	public decimal Latitude { get; set; }
    	public decimal Longitude { get; set; }
    }

    and the mapping

    public class WorkReportMap : EntityTypeConfiguration<WorkReport>
    {
    	public WorkReportMap()
    	{
    		HasOptional(x => x.Coordinate)
    					.WithMany()
    					.HasForeignKey(x => x.CoordinateID);
    
    	}
    }

    The Create() work perfect, but I have problem with the Update() where I asign the operation with the relation

    public override void Update(WorkReport entity)
    {
    	using (CustomContext context = new CustomContext())
    	{                               
    		var reportSel = context.WorkReports
    							.Include(x => x.Coordinate)
    							.First(x => x.ReportID == entity.ReportID);
    
    		
    		if (reportSel.Coordinate == null)
    			context.Entry(entity.Coordinate).State = EntityState.Added;
    		else
    			context.Entry(entity.Coordinate).State = EntityState.Modified;
    
    		
    		context.Entry(entity).State = EntityState.Modified;
    		context.SaveChanges();
    	}
    }

    I have the error

    An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

    The coordinate is optional then I detect three situations:

    - the update() receive un workreport without coordinate, but in the db exist, then I have remove the data in the db

    - the update() receive un workreport with coordinate, but in the db not exist, I need mark the Coordinate to add the relation

    - the update() receive un workreport with coordinate, in the db exist, but the data differs, I need mark the Coordinate to update

    How I can mark the relation without get this error ?

    greetings


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina


    Tuesday, September 24, 2013 12:59 PM

Answers

  • If it is that you create a new workreport which already exists in database, and the you query anther worreport like below:

     using (AssignStateContext db = new AssignStateContext())

                {

                    WorkReport entity = new WorkReport() { CoordinateID = 1, Description = "1", WorkReportID = 1 };

                    var reportSel = db.WorkReports

                                .Include(x => x.Coordinate)

                                .First(x => x.WorkReportID == entity.WorkReportID);

                    db.Entry(entity).State = EntityState.Modified;

                    db.SaveChanges();

                }

    So now there two workreports with the same key value exist in the dbcontext.

    Unfortunately, there is a problem for the ObjectStateManager that it cannot track multiple objects which are the same type with the same key.

    One way to fix it is to set one of them to be Detached as below:

     db.Entry(reportSel).State = EntityState.Detached;

     db.Entry(entity).State = EntityState.Modified;

    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.

    Friday, September 27, 2013 9:11 AM
    Moderator

All replies

  • Hello,

    With your code, I made a sample which is similar with yours.

    However, it runs ok, no exception is thrown.

    There is the sample below:

        public class WorkReport
    
        {
    
            public int WorkReportID { get; set; }
    
            public string Description { get; set; }
    
    
            public int? CoordinateID { get; set; }
    
            public Coordinate Coordinate { get; set; }
    
    
    }
    
    public class Coordinate
    
        {
    
            public int CoordinateID { get; set; }
    
    
            public decimal Latitude { get; set; }
    
            public decimal Longitude { get; set; }
    
    }
    
    class AssignStateContext : DbContext
    
        {
    
            public DbSet<Coordinate> Coordinates { get; set; }
    
            public DbSet<WorkReport> WorkReports { get; set; }
    
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
            {
    
                modelBuilder.Entity<WorkReport>().HasOptional(w => w.Coordinate).WithMany().HasForeignKey(w => w.CoordinateID);
    
            }
    
    }
    
    using (AssignStateContext db = new AssignStateContext())
    
                {
    
                    //db.Database.Create();
    
                    WorkReport entity = db.WorkReports.Find(1);
    
    
                    var reportSel = db.WorkReports
    
                                .Include(x => x.Coordinate)
    
                                .First(x => x.WorkReportID == entity.WorkReportID);
    
    
    
                    if (reportSel.Coordinate == null)
    
                        db.Entry(entity.Coordinate).State = EntityState.Added;
    
                    else
    
                        db.Entry(entity.Coordinate).State = EntityState.Modified;
    
    
    
                    db.Entry(entity).State = EntityState.Modified;
    
                    db.SaveChanges();
    
    
                }
    

    And my data:

    Thanks &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.

    Wednesday, September 25, 2013 2:19 AM
    Moderator
  • Hi

    Thanks for the answer

    I can see an error in the data, each workreport has its own coordinate

    in the example I can see that workreports 1 and 2 have the same coordinate

    I have the problem when Update the coordinate

    the coordinates are optional, I can create workreport without coordinate and then in other operation assigns one

    in this case I have the problem I need determinate which state to assign to related entity

    ---

    I use the linq query to get the workreport from the database and its coordinate related, this generate the error because when I can use

    context.Entry(entity).State = EntityState.Modified;

    the workreport already is in the context

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina


    Thursday, September 26, 2013 10:48 AM
  • If it is that you create a new workreport which already exists in database, and the you query anther worreport like below:

     using (AssignStateContext db = new AssignStateContext())

                {

                    WorkReport entity = new WorkReport() { CoordinateID = 1, Description = "1", WorkReportID = 1 };

                    var reportSel = db.WorkReports

                                .Include(x => x.Coordinate)

                                .First(x => x.WorkReportID == entity.WorkReportID);

                    db.Entry(entity).State = EntityState.Modified;

                    db.SaveChanges();

                }

    So now there two workreports with the same key value exist in the dbcontext.

    Unfortunately, there is a problem for the ObjectStateManager that it cannot track multiple objects which are the same type with the same key.

    One way to fix it is to set one of them to be Detached as below:

     db.Entry(reportSel).State = EntityState.Detached;

     db.Entry(entity).State = EntityState.Modified;

    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.

    Friday, September 27, 2013 9:11 AM
    Moderator