ObjectContext实例已被释放,不能再用于需要连接的操作

时间:2011-03-19 05:39:37

标签: c# .net asp.net-mvc-3 entity-framework exception-handling

我有这个观点:

@model MatchGaming.Models.ProfileQuery
@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>    
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm("Results", "Profiles")) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>ProfileQuery</legend>
        @Html.EditorFor(model=>model.SearchString)
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

我有HttpPost的这个控制器:

[HttpPost]
public ActionResult Results(ProfileQuery profileQuery)
{
    Debug.Write(profileQuery.SearchString);
    using(var db = new MatchGamingEntities())
    {
        var SearchUserName = db.Users.SingleOrDefault(a=> a.UserName.Contains(profileQuery.SearchString));
        var Users = from m in db.Users
                    join m2 in db.MyProfiles on m.UserId equals m2.UserId
                    where m.UserName == SearchUserName.UserName
                    select new UserViewModel
                    {
                        UserName = m.UserName,
                        LastActivityDate = m.LastActivityDate,
                        Address = m2.Address,
                        City = m2.City,
                        State = m2.State,
                        Zip = m2.Zip
                    };

        return View(Users.AsEnumerable());
    }
}

以下是结果视图:

@model IEnumerable<MatchGaming.Models.UserViewModel>    
@{
    ViewBag.Title = "Results";
}

<h2>Results</h2>

<fieldset>
    <legend>UserViewModel</legend>
    @foreach (var item in Model){
    <div class="display-label">UserName</div>
    <div class="display-field">@item.UserName</div>

    <div class="display-label">LastActivityDate</div>
    <div class="display-field">@String.Format("{0:g}", item.LastActivityDate)</div>

    <div class="display-label">Address</div>
    <div class="display-field">@item.Address</div>

    <div class="display-label">City</div>
    <div class="display-field">@item.City</div>

    <div class="display-label">State</div>
    <div class="display-field">@item.State</div>

    <div class="display-label">Zip</div>
    <div class="display-field">@item.Zip</div>
    }
</fieldset>

我一直收到这个错误:

  

ObjectContext实例已被释放,不能再用于需要连接的操作。

我无法弄清楚原因。

6 个答案:

答案 0 :(得分:51)

我猜测问题是你的LINQ查询的执行被推迟到你的视图开始访问它们。此时db已被处置。

试试这个:

return View(Users.ToList());

添加了ToList()

这会在处置db之前强制从数据库中获取。

答案 1 :(得分:11)

您的使用子句在查看有机会使用它之前处理(读取:销毁) MatchGamingEntities 数据库上下文。因此,虽然您可以在将用户传递给查看之前(或作为)枚举项目,但更好的方法是 放弃使用< 使用子句的/ em> ,让自然垃圾收集在你真正完成之后完成它的工作 - 直到View完成后才会这样做。

有关详细信息,请参阅this question on the Entity Framework and Connection Pooling

答案 2 :(得分:10)

问题在于这一行:

return View(Users.AsEnumerable());

枚举被懒惰地评估,并且因为你的MatchGamingEntities在你的视图循环遍历枚举之前被处理掉了,所以代码在它尝试这样做时就会死掉。

您必须找到一种方法来管理 db 对象的生命周期,使其超出控制器方法,或者将所有数据带入内存模型对象之前将它们传递给视图。

请参阅here以获得类似的解释。

答案 3 :(得分:9)

不好的做法,但你可以设置

this.ContextOptions.LazyLoadingEnabled = false;
constructor

Context

答案 4 :(得分:1)

问题是,当您执行以下操作时,您将发出浅拷贝:

 var Users = from m in db.Users
                join m2 in db.MyProfiles on m.UserId equals m2.UserId
                where m.UserName == SearchUserName.UserName
                select new UserViewModel
                {
                    UserName = m.UserName,
                    LastActivityDate = m.LastActivityDate,
                    Address = m2.Address,
                    City = m2.City,
                    State = m2.State,
                    Zip = m2.Zip
                };

您需要做的是创建一个UsersCopy,然后遍历用户将值复制到UsersCopy,然后返回UsersCopy以执行深层复制

这样的东西
List<User> UsersCopy = new List<User>();
foreach(user in Users){
  User u = new User();
  u.UserName = user.UserName;
  u.Address = user.Address;
  //...
  UsersCopy.Add(u);
}
return View(UsersCopy);

答案 5 :(得分:1)

如果您在显示子属性(即行项目)时遇到问题。这是对我有用的脏修复。修复了我没有检索对象的子项的问题:

header.MachineDataLines = header.MachineDataLines;