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)
问题是传递给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)
不太可能是延迟加载,这需要明确引用上下文,但在你的情况下应该没问题.