使用EF

时间:2015-10-16 11:28:17

标签: c# asp.net-mvc entity-framework repository-pattern unit-of-work

我正在尝试更好地了解UoW模式,因为我喜欢它的概念,但目前我很难节省实体。

问题是当我的控制器中的编辑(POST)操作触发时,只保存父实体并且子实体完好无损,即我收到以下错误:

  

附加“Access.Models.ApplicationParameter”类型的实体   失败,因为同一类型的另一个实体已经相同   主键值。使用“附加”方法或时,可能会发生这种情况   将实体的状态设置为“未更改”或“已修改”(如果有)   图中的实体具有冲突的键值。这可能是因为   某些实体是新的,尚未收到数据库生成的密钥   值。在这种情况下,使用“添加”方法或“已添加”实体状态   跟踪图形,然后将非新实体的状态设置为   “视情况而定”或“修改”。

注意:父实体应用可以有多个子 ApplicationParameter 实体。

控制器

    [HttpPost]
    public ActionResult Edit(ApplicationVM applicationVM)
    {
        Application application = ViewModelToModel(applicationVM);
        uow.ApplicationRepository.Update(application);

        foreach (var applicationParameterVM in applicationVM.ApplicationParameters)
        {
            ApplicationParameter applicationParameter = ViewModelToModel(applicationParameterVM);

            bool exists = uow.ApplicationParameterRepository.Exists(applicationParameter.idApplicationParameter);

            if (exists)
            {
                uow.ApplicationParameterRepository.Update(applicationParameter);
            }
            else
            {
                uow.ApplicationParameterRepository.Insert(applicationParameter);
            }
        }

        uow.Save();
        return View(applicationVM);
    }

ApplicationParameterRepository.cs(只是更新代码段)

    public void Update(ApplicationParameter entity)
    {
        db.Entry(entity).State = EntityState.Modified;
    }

UOW.cs

public class UnitOfWork : IDisposable
{
    private AMEntities db = null;

    public UnitOfWork()
    {
        db = new AMEntities();
    }

    //Add all the repository handles here
    IApplicationRepository applicationRepository = null;
    IApplicationParameterRepository applicationParameterRepository = null;
    IApplicationUserRepository applicationUserRepository = null;

    //Add all the repository getters here
    public IApplicationRepository ApplicationRepository
    {
        get
        {
            if (applicationRepository == null)
            {
                applicationRepository = new ApplicationRepository(db);
            }
            return applicationRepository;
        }
    }
    public IApplicationParameterRepository ApplicationParameterRepository
    {
        get
        {
            if (applicationParameterRepository == null)
            {
                applicationParameterRepository = new ApplicationParameterRepository(db);
            }
            return applicationParameterRepository;
        }
    }
    public IApplicationUserRepository ApplicationUserRepository
    {
        get
        {
            if (applicationUserRepository == null)
            {
                applicationUserRepository = new ApplicationUserRepository(db);
            }
            return applicationUserRepository;
        }
    }

    public void Save()
    {
        db.SaveChanges();
    }

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                db.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

问题:如何保存这些子实体?

2 个答案:

答案 0 :(得分:1)

确保您建立applicationParameterapplication之间的关系。使用导航属性或ID至少有三种方法可以做到这一点,我在代码中看不到这样的一行:

1

// if application have unique Id, for example it already has been saved in db
applicationParameter.ApplicationId = application.Id; 

2

applicationParameter.Application = application;

3

//if application is a EF-generated proxy 
application.ApplicationParameters.Add(applicationParameter); 

此外,在简单的情况下,如果实体已正确添加到上下文中,则不需要设置EntityState

答案 1 :(得分:1)

就我看来,你有两个选择。

  1. 最简单的方法是在Edit操作开始时获取实体。如果结果为null,则添加新值,否则使用新值更新实体并保存。这将确保父实体和所有子项处于相同的上下文中。

  2. 另一种方法是使用自我跟踪实体。看看Self Tracking Entities。这样您就可以处理实体的状态而不是EF。

  3. 问题是你只是将父级的状态设置为更新,每个子状态仍然被添加,所以它试图添加子实体而不是更新它们。