Asp.net mvc 3 EF 4.3.1代码优先更新相关表格 更新:

Asp.net mvc 3 EF 4.3.1代码优先更新相关表格 更新:,asp.net-mvc-3,entity-framework,entity-framework-4,entity-framework-4.1,Asp.net Mvc 3,Entity Framework,Entity Framework 4,Entity Framework 4.1,这让我快发疯了 经过大量的谷歌搜索等,我真的没有接近一个解决方案 然而,我发现了一件让我更加困惑的事情——在m_dbContext.SaveChanges()调用之前实体的“状态”。(请参阅下面的完整存储库代码) 为什么“oldPage”被分离 现在变得非常绝望!!;) 原件: 我似乎在EF代码首次正确更新相关表时遇到问题 在这个简化的示例中,“UpdateInfo”表正在使用新的日期时间进行OK更新。。。。但未使用新的“名称”值更新“页面”表 我正在通过DropCreateDatabaseAl

这让我快发疯了

经过大量的谷歌搜索等,我真的没有接近一个解决方案

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

为什么“oldPage”被分离

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

原件: 我似乎在EF代码首次正确更新相关表时遇到问题

在这个简化的示例中,“UpdateInfo”表正在使用新的日期时间进行OK更新。。。。但未使用新的“名称”值更新“页面”表

我正在通过DropCreateDatabaseAlways/override种子设定代码优先POCO。。。EF正在正确地创建测试表-因此在这一点上它似乎知道它在做什么

我确信这是我遗漏的简单/明显的东西

非常感谢大家的帮助

我的班级定义:

我的存储库代码:

publicpageget(int-id)
{
Page Page=m_dbContext.Pages.Single(p=>p.Id==Id);
返回页面;
}
公共无效更新(PagePostModel模型)
{
Page oldPage=Get(model.PageModel.Id);//在oldPage Name=“Hello”,DateUpdated=“去年”
Page newPage=Mapper.Map(model.PageModel);//在newPage Name=“再见”(AutoMapper)上
newPage.UpdateInfo=oldPage.UpdateInfo;//复制旧的UpdateInfo,因为它不包含在模型中
newPage.UpdateInfo.DateUpdated=DateTime.UtcNow;//更新到现在
oldPage=newPage;//复制我们从上面的dbContext抓取的更新页面(注意,这里一切看起来都很好..oldPage与预期一样)
m_dbContext.SaveChanges();//更新-仅更新“UpdateInfo”表-未更改“Pages”表:(((
}

正如您所知,实体框架中有一个变更跟踪api

为了跟踪从数据库检索到的实体的更改,DbContext使用其引用值

上面的“更新”函数将新页插入到旧页中。因此,DbContext永远不知道旧页是新页。因此,它是“分离的”

然而,对于UpdateInfo,它是oldPage中引用的副本,所以DbContext可以跟踪该引用的更改,所以它被“修改”

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

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

然后,使用附加和分离方法

这些方法帮助您从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();
Page newPage=Mapper.Map(model.PageModel);
//如果先附加,则会出现异常,
//因为有两个实体具有相同的id。
m_dbContext.Entry(oldPage).State=EntityState.Detached;
m_dbContext.Pages.Attach(newPage);
//如果不将IsModified设置为true,
//DbContext无法知道它已更改。
m_dbContext.Entry(newPage).State=EntityState.Modified;
m_dbContext.SaveChanges();

非常感谢您的及时回复-我尝试了该主题的各种变体…但是如何在没有赋值的情况下将“newPage”的内容转换为“oldpage”?非常受欢迎的示例代码只是更新“DateUpdated”值,而不是用户通过传递的模型所做的更改。谢谢!。它现在正在工作!请参阅“Detach”方法已被弃用,因此我不得不改用m_dc.Entry(oldPage).State=EntityState.Detached;再次-感谢您的帮助..非常感谢!感谢您提供的信息。我不知道DbContext中没有分离。我更新了答案
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 :(((
}
Page newPage = Mapper.Map<PageModel, Page>(model.PageModel);
oldPage.UpdateInfo = newPage.UpdateInfo; 
oldPage.UpdateInfo.DateUpdated = DateTime.UtcNow;
m_dbContext.SaveChanges();
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();