我有一个ASP.Net MVC项目,我在其中添加了一个查看学生实体 到我的Entity Framework 6存储库。
class Student
public long Id { get; set; }
public virtual Book Favorite { get; set; }
class Book
public long Id { get; set; }
public string Title { get; set; }
Favorite
属性是从视图中的下拉列表设置的。
在帖子的控制器中,只设置了书籍的Id
。
告诉实体框架,只添加学生,但不添加
在引用的书中,我将Book的EntityState设置为Unchanged as
描述here
保存更改后,我在数据库中有正确的学生记录,并且书记录保持不变,但是 每当我从我的存储库(而不是通过学生)查询该书时,我都会得到一本书实体 返回仅设置了Id并且Title和所有其他属性为null。
我的控制器(简化):
public ActionResult Create()
{
StudentViewModel result = new StudentViewModel();
result.BookList = new SelectList(DbContext.Books, "Id", "Name");
return View(result);
}
[HttpPost]
public ActionResult Create(StudentViewModel viewModel)
{
DbContext.Entry(viewModel.NewStudent.Favorite).State = EntityState.UnChanged);
DbContext.Add(viewModel.NewStudent);
DbContext.SaveChanges();
Book missingProperties =
DbContext.Books.Single(book => book.Id == viewModel.NewStudent.Favorite.Id);
}
我的观点(简化):
@using System.Linq
@model StudentViewModel
@using (Html.BeginForm())
{
...
@Html.TextBoxFor(model => model.NewStudent.Name)
@Html.DropDownListFor(model => model.NewStudent.Favorite.Id, Model.BookList)
...
}
答案 0 :(得分:1)
你应该在保存新学生之前查询Favorite
数据库(并检查那里是否有一个,因为你不应该发生什么来自客户端=),这样可以将本书送到上下文中,所以你只需将它设置给学生:
Book book = DbContext.Books.Single(book => book.Id == viewModel.NewStudent.Favorite.Id);
if(book!=null)
{
viewModel.NewStudent.Favorite = book;
}
else
{
throw new Exception();
}
DbContext.Add(viewModel.NewStudent);
DbContext.SaveChanges();
答案 1 :(得分:1)
问题是,Entity Framwork DbContext缓存实体。
使用延迟加载,您只需要对相关数据进行一些引用,实体框架将检查它是否已加载到内存中。如果没有,实体框架将在幕后创建并执行查询,填充相关数据。
默认情况下,Visual Studio将定义新创建的模型以将LazyLoadingEnabled设置为true。
(来自MSDN)
从db加载后,将不再为DbContext生命周期加载它。
EntityState.UnChanged
仅阻止Entity Framework将实体存储回数据库。但是每当第二次从上下文中检索实体时,不会从数据库中获取正确的值,而是修改后的,现在也在缓存中。
还需要刷新修改后的实体。将它附加在DbContext中,然后重新加载它。
Book result = Attach(book);
Entry(book).Reload();
我认为,这回答了这个问题,但我不确定GuruStron的回答是否使用了更好的模式。