Entity Framework DbSet.Find throws exception

与世无争的帅哥 提交于 2019-12-10 09:35:28

问题


I'm following a very basic example of code-first Entity Framework (version 4.1) in ASP.NET MVC 4 (using the EBuy example in O'Reilly's Programming ASP.NET MVC 4). I've searched for solutions to this and so far have drawn blank. The basic problem is this code in my controller:

public ActionResult Details(long id)
    {
        using (var db = new EbuyDataContext())
        {
            var rep = db.Auctions;
            var auction = rep.Find(id);
            return View(auction);
        }
    }

throws an ArgumentNullException Value cannot be null. Parameter name: key. when it hits the rep.Find(id) call. Interestingly, when it breaks into the code, the db.Auctions property has the 'Expanding the Results View will enumerate the IEnumerable' and if clicked, it shows my expected two entities which have just been retrieved from the database. The rep object however, does have 'Children could not be evaluated' when it is inspected.

Quite similar 'Create' code like this works okay:

[HttpPost]
    public ActionResult Create(Auction auction)
    {
        var db = new EbuyDataContext();
        db.Auctions.Add(auction);
        db.SaveChanges();

        return View(auction);
    }

This is my db context:

namespace Ebuy.DataAccess
{
    public class EbuyDataContext : DbContext
    {
        public DbSet<Auction> Auctions { get; set; } 
    }
}

and this is my model class:

namespace Ebuy.DomainModel
{
    public class Auction
    {
        public long Id { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public decimal StartPrice { get; set; }
        public decimal CurrentPrice { get; set; }
        public DateTime StartTime { get; set; }
        public DateTime EndTime { get; set; }
    }
}

I did find one reference which talked about the POCO's and the dbcontext being in different namespaces or assemblies. Does anyone know why the Create code works and the Find doesn't?

Edit: The stacktrace is:

System.ArgumentNullException was unhandled by user code
Message=Value cannot be null. Parameter name: key Source=mscorlib
ParamName=key StackTrace: at System.Collections.Generic.Dictionary2.FindEntry(TKey key) at System.Collections.Generic.Dictionary2.ContainsKey(TKey key) at System.Data.Entity.Internal.InternalContext.TryUpdateEntitySetMappingsForType(Type entityType) at System.Data.Entity.Internal.InternalContext.IsEntityTypeMapped(Type entityType) at System.Data.Entity.Internal.Linq.InternalSet1.Find(Object[] keyValues) at System.Data.Entity.DbSet1.Find(Object[] keyValues) at Ebuy.Website.Controllers.AuctionsController.Details(Int64 id) in C:\Users\John\Documents\Visual Studio 2010\Projects\Ebuy.Website\Ebuy.Website\Controllers\AuctionsController.cs:line 26 at lambda_method(Closure , ControllerBase , Object[] ) at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c_DisplayClass42.b_41() at System.Web.Mvc.Async.AsyncResultWrapper.<>c_DisplayClass81.<BeginSynchronous>b__7(IAsyncResult _) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.End() at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c_DisplayClass37.<>c_DisplayClass39.b_33() at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c_DisplayClass4f.b_49() InnerException:

Edit 2: The table does have the Id column as the primary key. Update: Based on nemesv's comment, I checked the versions. I'm using .NET Framework v 4.0. The MVC Web app, when created, used Nuget to get EF version 5.0 (although the actual reference is to EF runtime 4.0.30319 v4.4.0.0). I added the DataAccess project and gave it a reference to a different EF (runtime 4.0.30319 v4.1.0.0). I've changed the DataAccess project's reference to the same EF as the Web app and now I get a different exception: InvalidOperationException The context cannot be used while the model is being created. This appears to be an issue when using EF across an N-tier application, so I'll follow up this thread and report back.

Fix: I read some stuff about LazyLoading settings in EF and also how loading takes place when you access a property of an entity. As I'm not really accessing an entities property before I try and find one and thinking that perhaps LazyLoading is the default in EF 5.0, I added a default constructor to my EbuyDataContext class as follows:

public class EbuyDataContext : DbContext
{
    public EbuyDataContext()
    {
        //Configuration.LazyLoadingEnabled = false;
    }

    public DbSet<Auction> Auctions { get; set; } 
}

I also set the LazyLoadingEnabled parameter to false and then ran it and Voila! Success! However, I thought I would double-check this, so I commented out the LazyLoadingEnabled parameter, did a clean rebuild and it still worked. I commented out the default constructor and now it still works - did something else change when I ran it with the LazyLoadingEnabled parameter in place?


回答1:


In EF (at least 4 and 5) lazy loading IS the default configuration. Also, try explicitly marking your Id as a Key using the KeyAttribute decoration.

public class Auction
{
    [Key]
    public long Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public decimal StartPrice { get; set; }
    public decimal CurrentPrice { get; set; }
    public DateTime StartTime { get; set; }
    public DateTime EndTime { get; set; }
}


来源:https://stackoverflow.com/questions/13148263/entity-framework-dbset-find-throws-exception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!