EF Code First not returning object as DynamicProxies until after the HTTP Request is complete
I'm getting some strange behaviour from EF Code First when I add an object to the database and select it back from the database in the same HTTP request.
When I retrieve it, it is returned as the object type rather than of type System.Data.Entity.DynamicProxies so the lazy loading d开发者_开发百科oesn't work.
If I retrieve the same object in the next HTTP Request then it is return as type System.Data.Entity.DynamicProxies and the lazy loading works fine.
Do I need to do something to the object or the context to get a DynamicProxy returned? Or is this how EF Code First is meant to work, if so how do I get around this issue?
I've even recreated the problem using the sample code in the NuGet packages.
Here's the code that I used to recreate the problem:
public ActionResult Index() {
var blogContext = new BlogContext();
var posts = blogContext.Posts;
ViewBag.Message = "Welcome to ASP.NET MVC!";
ViewBag.Posts = posts;
return View();
}
public ActionResult AddPost() {
var blogContext = new BlogContext();
var post = new Post() {
PublishDate = DateTime.Now,
Text = "Text",
Title = "Title",
};
blogContext.Posts.Add( post );
blogContext.SaveChanges();
var post2 = blogContext.Posts.Find( post.ID );
return RedirectToAction( "Index" );
}
public ActionResult GetPost(int id) {
var blogContext = new BlogContext();
var post = blogContext.Posts.Find( id );
ViewBag.Post = post;
return View();
}
When I get post2 in the AddPost action it is return of type MvcApplication.Models.Post where as when I return the same post in the GetPost action it is of type System.Data.Entity.DynamicProxies.Post.
The above code was recreated using the default MVC3 Application from the MVC 3 Tools Update I also installed the following NuGet packages: EntityFramework.Sample and EntityFramework.SqlServerCompact.
If anyone can recreate the problem or has a solution for this then it would be greatly appreciated.
In C#, if you call new Post()
, then you're going to get a Post
instance, not an instance of a proxy subtype of Post
. To get a proxy, you have to call something different.
You can, e.g., call DbSet<T>.Create
:
var post = blogContext.Posts.Create();
post.PublishDate = DateTime.Now;
Total guess: try and use blogContext.Posts.Create()
rather than new Post()
. That way, your original object will be created by EF rather than be a naked CLR object.
You have a few options...
If you don't mind instantiating from the context, you can do:
var post = blogContext.Posts.Create();
This won't work as great if you are working with a repository (since your context will likely be encapsulated by the repository).
If you end up using a repository, one option is to explicitly load the related entities after attaching / saving. e.g.
// Load the related entity
context.Entry(post).Reference(u => u.Notes).Load();
One other option may be (haven't tested) to not use Find after you save. If you use find, EF will try to look in the context first.
精彩评论