开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜