EF 4.3.1代码优先更新相关表

时间:2012-05-10 13:22:19

标签: asp.net-mvc-3 entity-framework entity-framework-4 entity-framework-4.1

更新

现在这让我发疯了!

经过谷歌搜索等等。我真的没有接近解决方案.....

但是我发现有一件事让我更加困惑 - 在m_dbContext.SaveChanges()调用之前的实体的“状态”。 (请参阅下面的完整存储库代码)

var updateInfoState = m_dc.Entry(oldPage.UpdateInfo).State; // State is 'Modified'
var oldPageState = m_dc.Entry(oldPage).State;               // State is 'Detached' 

this.m_dc.SaveChanges();

为什么“oldPage”分离?

现在变得非常绝望!! ;)

原件:

我似乎遇到了EF Code-First正确更新相关表格的问题。

在这个简化的示例中,'UpdateInfo'表正在使用新的DateTime更新OK ....但是'Pages'表没有使用新的'Name'值进行更新。

我通过DropCreateDatabaseAlways / override Seed播种代码优先的POCO ......并且EF正在正确地创建测试表 - 所以此时它似乎知道它正在做什么....

我确信这很简单/显而易见我错过了!

非常感谢所有人的帮助!

我的班级定义:

public class Page
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual UpdateInfo UpdateInfo { get; set; }  // virtual For Lazy loading
}

[Table("UpdateInfo")]                                   // much better than EF's choice of UpdateInfoes! 
public class UpdateInfo
{
    public int Id { get; set; }
    public DateTime DateUpdated { get; set; }
}

public class DomainContext : DbContext
{
    public DbSet<Page> Pages { get; set; }
    public DbSet<UpdateInfo> UpdateInfo { get; set; }
}

由Code-First创建的表

Pages Table
===========

    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](max) NULL,
    [UpdateInfo_Id] [int] NULL,

UpdateInfo Table
================

    [Id] [int] IDENTITY(1,1) NOT NULL,
    [DateUpdated] [datetime] NOT NULL,

我的存储库代码:

public Page Get(int id)
{
    Page page = m_dbContext.Pages.Single(p => p.Id == id);
    return page;
}

public void Update(PagePostModel model)
{
    Page oldPage = Get(model.PageModel.Id);                         // on oldPage Name = "Hello", DateUpdated = "Last Year"

    Page newPage = Mapper.Map<PageModel, Page>(model.PageModel);    // on newPage Name = "Goodbye"  (AutoMapper)
    newPage.UpdateInfo = oldPage.UpdateInfo;                        // take a copy of the old UpdateInfo since its not contained in the model

    newPage.UpdateInfo.DateUpdated = DateTime.UtcNow;               // update to now

    oldPage = newPage;                                              // copy the updated page we grabbed from dbContext above (NB Everything looks great here..oldPage is as expected)

    m_dbContext.SaveChanges();                                      // update - only the 'UpdateInfo' table is being updated - No change to 'Pages' table :(((
}

1 个答案:

答案 0 :(得分:2)

如您所知,Entity Framework中有一个更改跟踪器API。

要跟踪从数据库中检索到的实体的更改,DbContext将使用其参考值。

上面的“更新”功能将newPage插入到oldPage中。所以,DbContext永远不会知道oldPage是一个newPage。所以,它是“超然的”。

但是,对于UpdateInfo,它是oldPage中的引用副本,因此DbContext可以跟踪它的更改。所以,它被“修改”了。

要解决这个问题,请使用下面的代码怎么样?

Page newPage = Mapper.Map<PageModel, Page>(model.PageModel);
oldPage.UpdateInfo = newPage.UpdateInfo; 
oldPage.UpdateInfo.DateUpdated = DateTime.UtcNow;
m_dbContext.SaveChanges();

<强>更新

然后,使用Attach&amp;分离方法。

这些方法可以帮助您从DbContext中附加和分离实体。

Page newPage = Mapper.Map<PageModel, Page>(model.PageModel);
// if you attach first, there will be an exception, 
// because there is two entities having same id.
m_dbContext.Entry(oldPage).State = EntityState.Detached; 
m_dbContext.Pages.Attach(newPage);
// if you don't set IsModified = true,
// DbContext cannot know it is changed.
m_dbContext.Entry(newPage).State = EntityState.Modified;
m_dbContext.SaveChanges();