由于已使用MVC 4处理了DbContext,因此无法完成操作

San*_*wat 20 c# linq asp.net-mvc entity-framework dbcontext

我知道这个问题被问过这么多次.我已阅读并实施了所有解决方案但未获得成功.当我使用EF从数据库检索数据并在View上使用此模型后与模型绑定时,我收到此错误.

我的控制器代码是

using System.Linq;
using System.Web.Mvc;
using JsonRenderingMvcApplication.Models;

namespace JsonRenderingMvcApplication.Controllers
{
    public class PublisherController : Controller
    {
        public ActionResult Index()
        {
            PublisherModel model = new PublisherModel();
            using (DAL.DevelopmentEntities context = new DAL.DevelopmentEntities())
            {               
                model.PublisherList = context.Publishers.Select(x =>
                                        new SelectListItem()
                                        {
                                            Text = x.Name,
                                            Value = x.Id.ToString()
                                        }); ;
                           }
            return View(model);
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

我的查看代码是

@model JsonRenderingMvcApplication.Models.PublisherModel

@{
    ViewBag.Title = "Index";
}
<div>
    @Html.DisplayFor(model=>model.Id)
    @Html.DropDownListFor(model => model.Id, Model.PublisherList);
</div>
<div id="booksDiv">

</div>
Run Code Online (Sandbox Code Playgroud)

我的型号代码是

using System.Collections.Generic;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;

namespace JsonRenderingMvcApplication.Models
{
    public class PublisherModel
    {
        public PublisherModel()
        {
            PublisherList = new List<SelectListItem>();
        }

        [Display(Name="Publisher")]
        public int Id { get; set; }
        public IEnumerable<SelectListItem> PublisherList { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的实体代码是

namespace JsonRenderingMvcApplication.DAL
{
    using System;
    using System.Collections.Generic;

    public partial class Publisher
    {
        public Publisher()
        {
            this.BOOKs = new HashSet<BOOK>();
        }

        public int Id { get; set; }
        public string Name { get; set; }
        public string Year { get; set; }

        public virtual ICollection<BOOK> BOOKs { get; set; }
    }
}     
Run Code Online (Sandbox Code Playgroud)

是的,这个实体有一个导航属性,但我不想要那个实体数据,所以我不想包含它.

谢谢

Han*_*ney 61

您遇到的问题是由于LINQ的延迟执行.对于那些还没有意识到LINQ如何工作的开发人员来说,这是非常困难的.我有一篇很棒的博客文章,但核心概念是你必须强制对集合进行枚举,以使LINQ代码立即运行而不是以后运行.这意味着改变这个:

model.PublisherList = context.Publishers.Select(x =>
    new SelectListItem()
    {
        Text = x.Name,
        Value = x.Id.ToString()
    });
Run Code Online (Sandbox Code Playgroud)

对此:

model.PublisherList = context.Publishers.Select(x =>
    new SelectListItem()
    {
        Text = x.Name,
        Value = x.Id.ToString()
    }).ToList();
Run Code Online (Sandbox Code Playgroud)

注意.ToList()那里强制枚举.

您的LINQ查询是延迟的,这意味着它不会在您的控制器上运行,而是在您的视图中运行,可能在您的视图中循环集合(这会强制枚举并因此运行LINQ).因为您正在使用该using语句来处理您的数据库上下文(这当然是一种很好的做法),所以在您到达视图之前会先处理该上下文,该视图会针对已处置的上下文执行代码.强制using语句中的枚举将在那时运行代码,而不是在处理上下文时运行,并防止出现此问题.

  • 很好的答案.@Sandeep.如果您对.ToList()的内容感到好奇,我强烈建议您阅读文档.http://msdn.microsoft.com/en-us/library/bb342261%28v=vs.110%29.aspx (2认同)
  • 完全是@Sandeep.但是`List <T>`不支持延迟执行,因此代码立即执行.`IEnumerable <T>`支持延迟执行,这对于跨多个投影/过滤器/查询的LINQ效率至关重要.这就是为什么LINQ几乎总是对`IEnumerable <T>`或`IQueryable <T>`接口起作用的原因. (2认同)