现在这让我发疯了!
经过谷歌搜索等等。我真的没有接近解决方案.....
但是我发现有一件事让我更加困惑 - 在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 :(((
}
答案 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();