MVC 5 DropDownList表示DbContext被处理?

时间:2016-09-06 13:41:06

标签: c# asp.net-mvc asp.net-mvc-5

我以为我开始明白如何在MVC中使用DDL,但我想我还没有真正得到他们正确的设置。

我有一个DropDownList,我正在从Entity Framework填充并使用存储库。我可以调试代码并看到ViewModel正在填充值,但是一旦我到达View I get和error "The operation cannot be completed because the DbContext has been disposed"。当我到View时,我还以为不再需要DbContext吗?

我尝试了Html.DropDownList和Html.DropDownListFor的不同组合,每次我都想出相同的消息。我确信这很简单,我只是不理解,但我一直在寻找不同的例子,尝试几种不同的组合而没有任何运气。

这是我的ViewModel

public class AssignCounselorViewModel
{
    public IEnumerable<SelectListItem> listMerits { get; set; }

    public int MeritSelectedId { get; set; }
}

这是我的控制器:

public ActionResult AssignCounselor()
{
    var viewModel = new AssignCounselorViewModel();
    viewModel.listMerits = MeritCounselorRepository.GetAllMerits();

    return View(viewModel);
}

这是我的存储库:

public static IEnumerable<SelectListItem> GetAllMerits()
{
    using (DataContext ctx = new DataContext())
    {
        var results = (from m in ctx.MeritBadges
                       select new SelectListItem
                       {
                           Value = m.ID.ToString(),
                           Text = m.MeritBadgeName
                        }
                       ).OrderBy(o => o.Text);

        return new SelectList(results, "Value", "Text");
    }
}

这是我的观点:

<div class="row">
    <div class="col-md-12">
        @Html.DropDownListFor(m => m.listMerits,
                new SelectList(Model.listMerits, "Text", "Value"))
    </div>
</div>

以下是我尝试的其他一些组合。

@Html.DropDownList("ddlMerit", new SelectList(Model.listMerits, "Value", "Text"), new { style = "width:100px;height:31px" })


@Html.DropDownListFor(m => Model.listMerits, Model.listMerits, "--Select--");

2 个答案:

答案 0 :(得分:2)

试试这个

public static IEnumerable<SelectListItem> GetAllMerits()
{
    using (DataContext ctx = new DataContext())
    {
        var results = (from m in ctx.MeritBadges
                       select new SelectListItem
                       {
                           Value = m.ID.ToString(),
                           Text = m.MeritBadgeName
                       }
                       ).OrderBy(o => o.Text).ToArray(); // .ToArray() => materialize collection. After this data will be returned from database.

        return new SelectList(results, "Value", "Text"); 
    }
}

答案 1 :(得分:0)

扩展tym32167的答案,这应解决问题...

using (DataContext ctx = new DataContext())
{
    var results = (from m in ctx.MeritBadges
                   select new SelectListItem
                   {
                       Value = m.ID.ToString(),
                       Text = m.MeritBadgeName
                    }
                   ).OrderBy(o => o.Text);

    return new SelectList(results, "Value", "Text");
}

这将返回IQueryable<SelectListItem>,这是一个尚未针对数据库执行的查询,但包含在发送执行命令时要调用的指令。这将在范围内的中返回,该范围内的DbContext将在调用完成后处理。执行IQueryable后,结果将变为某种IEnumerable.ToList变为List<T>.ToArray()变为数组等) ,DbContext被处置。

所以当你拨打IQueryable<MeritBadge>两次时,就像这样:

<div class="row">
    <div class="col-md-12">
        @Html.DropDownListFor(m => m.listMerits,
                new SelectList(Model.listMerits, "Text", "Value"))
    </div>
</div>

第一个实例m => m.listMerits将执行查询并处理上下文;然后调用model.ListMerits,它将尝试再次执行IQueryable以枚举数据,但上下文已经处理完毕。

编辑:tym32167指出我的IQueryable类型错了。