使用现有子项在EF中保存项目

时间:2013-12-12 13:52:03

标签: c# asp.net-mvc entity-framework

我在保存与Section有1-M关系的对象(FeatureType)时遇到一些问题。

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

如果ItemTypes是新的,我没有问题并且插入正确完成。

但是如果我想添加一些现有的ItemTypes即可获得此错误:

  

实体对象不能被多个实例引用   IEntityChangeTracker。

我一直在阅读这个问题,但我还没有找到解决问题的方法,这可能是因为它设计了我的应用程序。

从我的viewModel到我的Model,我正在获取部分ID,并从我的SectionRepository获取部分Object,如下所示:

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

这就是给我带来问题的原因,因为现在已经由具有自己的上下文的SectionRepository跟踪了该部分。

我该如何解决这个问题?我尝试使用现有ID创建一个新部分,但它只是创建了一个空对象。

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

更新

要保存我的实体,我只需使用:

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

更新2:这就是我拥有我的存储库的方式,我不想管理我的控制器中的任何EF,而是使用某种存储库或服务。

 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
}

2 个答案:

答案 0 :(得分:1)

你说SectionRepository有自己的背景。这会给你带来麻烦。存储库应该共享上下文。上下文是工作单元和存储库模式的组合。您需要将两种模式分开:

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

修改

您可以通过实施自己的工作单元模式来避免在控制器中使用DbContext

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

    int Save();
}

然后在你的控制器中:

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

更多参考资料:

Implementing the Repository and Unit of Work

Repository and Unit of Work in Entity Framework

John Papa's original source code

答案 1 :(得分:0)

简单地说,您获得的错误意味着实体是从DbContext的不同实例返回的,而不是现在尝试保存的实例。确保您没有在存储库中使用两个不同的using,并且您的存储库总是在每个实例中使用相同的DbContext