EF4.3代码优先,MVC,在POST操作中附加后的延迟加载

use*_*502 2 asp.net-mvc entity-framework lazy-loading model-binding

我在MVC 3应用程序中使用Entity Framework 4.3和Code-First.我有一个POST操作,它将实体作为其'参数,然后将实体标记为已修改以更新数据库.它是一个Document实体,它引用了File Type.

 [HttpPost]
 public ActionResult Example(Document model)
 {
     // fileType is null, as expected
     var fileType = model.FileType;

     // attach and mark the entity as modified, save changes
     Context.Entry(model).State = EntityState.Modified;
     Context.SaveChanges();

     // fileType is still null?
     fileType = model.FileType;

     return View(model);
 }
Run Code Online (Sandbox Code Playgroud)

将实体附加到上下文后,我不应该在该实体上延迟加载属性吗?

有趣的是,当我在控制台应用程序中尝试这个时,它似乎工作.

static void Main()
{
    // create a new context
    var context = new Context();

    // get the first document and detach it
    var doc = context.Documents.First();
    context.Entry(doc).State = EntityState.Detached;

    // fileType is null, as expected
    var fileType = doc.FileType;

    // dispose and create a new context
    context.Dispose();
    context = new Context();

    // attach the entity and mark it as modified
    context.Entry(doc).State = EntityState.Modified;

    // fileType is not null, which is the desired outcome
    fileType = doc.FileType;
}
Run Code Online (Sandbox Code Playgroud)

Art*_*ers 7

问题是传递给post方法的实体不是代理,可能是因为它是使用普通的"new"运算符在Entity Framewortk之外创建的.

这里有一些选择.首先,您可以使用该DbSet.Create方法修改MVC控制器以创建代理实例.我听说有可能以这种方式修改MVC控制器,但从未尝试过.例如,而不是做:

var doc = new Document();
Run Code Online (Sandbox Code Playgroud)

在控制器中,你会做:

var doc = context.Documents.Create();
Run Code Online (Sandbox Code Playgroud)

如果实体具有适当的虚拟属性,则create方法允许EF为延迟加载创建代理,在您的情况下,它看起来像是这样.

第二个可能更容易的选择是不使用延迟加载,而是使用显式加载API.例如,要加载FileType:

var fileType = context.Entry(doc).Reference(d => d.FileType).Load();
Run Code Online (Sandbox Code Playgroud)

不太可能是延迟加载,这需要明确引用上下文,但在你的情况下应该没问题.

  • 谢谢!使用您的解释,我能够找到一个简单的解决方案来实现生成代理的模型绑定器.这是帮助我的文章的链接.http://bit.ly/ydCjOm (3认同)