-1

Im having some problems saving an object (FeatureType) that have a 1-M relationship with Section.

public class FeatureType
    {
        public int Id { get; set; }

        public string Name { get; set; }

        [ForeignKey("SectionId")]
        public Section Section { get; set; }

        public virtual List<ItemType> ItemTypes { set; get; }
    }

    public class Section
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public int Order { get; set; }

        public virtual List<FeatureType> Features { get; set; }
    }

If The ItemTypes are new i have no problem and the insert is done correctly.

But if i want to add some existing ItemTypes im getting this Error:

An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

I have been reading about this problem but i havent found a way to solve it, and it might be because of how its designed my application.

Whem im mappinig from my viewModel to my Model, im getting the section ID and getting the section Object from my SectionRepository as this:

 private Section GetSection()
        {
            var section = _sectionRepository.GetSection(SectionId);
            return section;
        }

And this is what is giving me the problem, as the section is now been tracked by the SectionRepository that have its own context.

How can i solve this? I have tried just creating a new section with the existing ID but it just create me an empty object.

private Section GetSection()
            {
                var section = new Section{Id=SectionId};
                return section;
            }

UPDATE

To save my entity i just use :

_repository.Create(featureType.ToModel());

    public FeatureType ToModel()
        {
            var ft = new FeatureType
                         {
                             Name = Name,
                             ControlType = (ControlType)ControlType,
                             Order = Order,
                             Required = Required,
                             RequiredText = RequiredText,
                             ItemTypes = GetItemTypes().ToList(),
                             Section = GetSection(),
                         };

            return ft;
        }

UPDATE 2: This is how i have my repositories, i wouldn't like to manage any EF in my controller but with some kind of repository or service.

 public class EFBaseRepository
    {
        protected MyContext Db = new MyContext();

        public void Dispose(bool disposing)
        {
            Db.Dispose();
        }
    }

 public class EFFeatureTypeRepository : EFBaseRepository, IFeatureTypeRepository
    {
        public IQueryable<FeatureType> GetFeatureTypes
        {
            get { return Db.FeatureTypes.Include("Section").Include("ItemTypes"); }
        }

 public Message Create(FeatureType feature)
        {
            try
            {
                Db.FeatureTypes.Add(feature);
                Db.SaveChanges();
                return new Message();
            }
            catch (Exception e)
            {
                throw;
                // return new Message(e, string.Format("Error Creating {0}", feature.GetType()));
            }
        }

//..Other Methods
}
Luis Tellez
  • 2,785
  • 1
  • 20
  • 28
  • 1
    check this please http://stackoverflow.com/questions/14307838/entity-framework-adding-existing-child-poco-to-new-parent-poco-creates-new-chi – LINQ2Vodka Dec 12 '13 at 14:08

2 Answers2

1

You say that the SectionRepository has its own context. That is going to cause you problems. The repositories should share a context. The context is a combination of the unit of work and repository patterns. You need to separate the two patterns:

How to migrate towards unit-of-work and repository pattern

EDIT

You can avoid having the DbContext in the Controller by implementing your own Unit Of Work pattern.

public interface IUnitOfWork : IDisposable
{
    ISectionRepository SectionRepository {get;}
    //etc

    int Save();
}

then in your controller:

public ActionResult Create(FeatureTypeCreate featureType)
{
   _Uow.SectionRepository.Create(featureType.ToModel());
   _Uow.Save(); //Saving is the responsibility of the Unit Of Work 
                //not the Repository
}

More references:

Implementing the Repository and Unit of Work

Repository and Unit of Work in Entity Framework

John Papa's original source code

Community
  • 1
  • 1
Colin
  • 22,328
  • 17
  • 103
  • 197
  • Thanks colin, this does look like what i need, i will read it carefully and try to see if i can implement it. – Luis Tellez Dec 12 '13 at 16:56
  • Is there any way to avoid having the context called in my controller? This is what i was trying to do with my Repositories. – Luis Tellez Dec 12 '13 at 17:01
  • please check my updated question to see how i have my repositories to see how could we fix it. – Luis Tellez Dec 12 '13 at 17:13
  • 1
    Thanks! this http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application was the right solution for me. – Luis Tellez Dec 12 '13 at 18:54
0

Simply, the error you're getting means that the entities were returned from a different instance of your DbContext than from which they are now trying to be saved. Make sure that you're not doing something like using two different usings around your repository and that your repository always makes use of the same DbContext per instantiation.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • Please check my updated question to see how i have my repositories to see how could we fix it, i understand this is the problem, but i dont know how to solve it. – Luis Tellez Dec 12 '13 at 17:13