【发布时间】:2012-10-20 08:09:09
【问题描述】:
我正在关注 ASP.NET MVC 4 中代码优先实体框架(4.1 版)的一个非常基本的示例(使用 O'Reilly 的 Programming ASP.NET MVC 4 中的 EBuy 示例)。我一直在寻找解决方案,到目前为止还一片空白。基本问题是我的控制器中的这段代码:
public ActionResult Details(long id)
{
using (var db = new EbuyDataContext())
{
var rep = db.Auctions;
var auction = rep.Find(id);
return View(auction);
}
}
抛出 ArgumentNullException 值不能为空。参数名称:key. 当它遇到 rep.Find(id) 调用时。有趣的是,当它闯入代码时,db.Auctions 属性具有“扩展结果视图将枚举 IEnumerable”,如果单击它,它会显示我预期的两个刚刚从数据库中检索到的实体。然而,rep 对象在检查时确实有“无法评估子项”。
类似这样的“创建”代码可以正常工作:
[HttpPost]
public ActionResult Create(Auction auction)
{
var db = new EbuyDataContext();
db.Auctions.Add(auction);
db.SaveChanges();
return View(auction);
}
这是我的数据库上下文:
namespace Ebuy.DataAccess
{
public class EbuyDataContext : DbContext
{
public DbSet<Auction> Auctions { get; set; }
}
}
这是我的模型类:
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; }
}
}
我确实找到了一篇关于 POCO 和 dbcontext 位于不同名称空间或程序集中的参考资料。 有谁知道为什么 Create 代码有效而 Find 无效?
编辑:堆栈跟踪是:
System.ArgumentNullException 未被用户代码处理
Message=Value 不能为空。参数名称:key Source=mscorlib
参数名称=键堆栈跟踪: 在 System.Collections.Generic.Dictionary2.FindEntry(TKey key) at System.Collections.Generic.Dictionary2.ContainsKey(TKey 键) 在 System.Data.Entity.Internal.InternalContext.TryUpdateEntitySetMappingsForType(类型 实体类型) 在 System.Data.Entity.Internal.InternalContext.IsEntityTypeMapped(类型 实体类型) 在 System.Data.Entity.Internal.Linq.InternalSet1.Find(Object[] keyValues) at System.Data.Entity.DbSet1.Find(Object[] keyValues) 在 C:\Users\John\Documents\Visual Studio 中的 Ebuy.Website.Controllers.AuctionsController.Details(Int64 id) 2010\Projects\Ebuy.Website\Ebuy.Website\Controllers\AuctionsController.cs:line 26 在 lambda_method(闭包,ControllerBase,对象 []) 在 System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase 控制器,Object[] 参数) 在 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext 控制器上下文,IDictionary2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 参数) 在 System.Web.Mvc.Async.AsyncControllerActionInvoker.c_DisplayClass42.b_41() 在 System.Web.Mvc.Async.AsyncResultWrapper.c_DisplayClass81.<BeginSynchronous>b__7(IAsyncResult _) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.End() 在 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult 异步结果) 在 System.Web.Mvc.Async.AsyncControllerActionInvoker.c_DisplayClass37.c_DisplayClass39.b_33() 在 System.Web.Mvc.Async.AsyncControllerActionInvoker.c_DisplayClass4f.b_49() 内部异常:
编辑 2: 该表确实将 Id 列作为主键。 更新:根据 nemesv 的评论,我检查了版本。我正在使用 .NET Framework v 4.0。 MVC Web 应用在创建时使用 Nuget 获取 EF 版本 5.0(尽管实际引用的是 EF 运行时 4.0.30319 v4.4.0.0)。我添加了 DataAccess 项目并为其提供了对 不同 EF(运行时 4.0.30319 v4.1.0.0)的引用。我已将 DataAccess 项目的引用更改为与 Web 应用程序相同的 EF,现在我得到一个不同的异常: InvalidOperationException 在创建模型时无法使用上下文。在跨 N 层应用程序使用 EF 时,这似乎是一个问题,因此我将跟进此线程并进行报告。
修复:我阅读了一些关于 EF 中的 LazyLoading 设置以及访问实体属性时如何加载的内容。由于我在尝试查找实体属性之前并没有真正访问实体属性,并认为 LazyLoading 可能是 EF 5.0 中的默认值,因此我在 EbuyDataContext 类中添加了一个默认构造函数,如下所示:
public class EbuyDataContext : DbContext
{
public EbuyDataContext()
{
//Configuration.LazyLoadingEnabled = false;
}
public DbSet<Auction> Auctions { get; set; }
}
我还将 LazyLoadingEnabled 参数设置为 false,然后运行它,瞧!成功! 但是,我想我会仔细检查这一点,所以我注释掉了 LazyLoadingEnabled 参数,进行了干净的重建,它仍然有效。我注释掉了默认构造函数,现在它仍然可以工作 - 当我使用 LazyLoadingEnabled 参数运行它时是否有其他变化?
【问题讨论】:
-
能否请您也发布堆栈跟踪?
-
表的Id列是否标记为主键?
-
您使用的是 4.0 还是 4.5 哪个 .net 版本?引用的
EntityFramework.dll的确切版本号是多少? -
你为什么不使用 lambda 来传递条件/谓词?
rep.Find(a => a.Id == id) -
@Rikkos:DbSet Find(object[] keyvalues) 的签名 (msdn.microsoft.com/en-us/library/…)
标签: asp.net-mvc entity-framework ef-code-first