web-dev-qa-db-fra.com

L'instance ObjectContext a été supprimée et ne peut plus être utilisée pour les opérations qui nécessitent une connexion

J'ai cette vue:

@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>

J'ai ce contrôleur pour le 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());
    }
}

Voici la vue des résultats:

@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>

Je reçois toujours cette erreur:

L'instance ObjectContext a été supprimée et ne peut plus être utilisée pour les opérations qui nécessitent une connexion.

Je ne comprends pas pourquoi.

40
anthonypliu

Je suppose que le problème est que l'exécution de votre requête LINQ a été différée jusqu'à ce que vous commenciez à y accéder sur votre vue. À ce stade, db a déjà été supprimé.

Essaye ça:

return View(Users.ToList());

ToList ajouté ()

Cela forcera l'extraction de la base de données avant de supprimer db.

51
Philip Fourie

Votre utilisant la clause supprime (lisez: détruisant) le contexte MatchGamingEntities db avant le Voir a une chance de l'utiliser. Ainsi, alors que vous pouvez simplement énumérer les éléments avant (ou en tant que), vous passez le Utilisateurs à la vue , une meilleure approche est de abandonnez votre utilisation du en utilisant et laissez le garbage collection naturel faire son travail après que vous en ayez vraiment fini - ce qui ne se fera qu'après que la vue soit terminée.

Pour plus d'informations, consultez cette question sur Entity Framework et Connection Pooling .

11
witttness

Le problème est cette ligne:

return View(Users.AsEnumerable());

L'énumération est évaluée paresseusement, et puisque votre MatchGamingEntities est supprimé avant que votre vue puisse parcourir l'énumération, le code meurt lorsqu'il essaie de faire exactement cela.

Vous devrez soit trouver un moyen de gérer la durée de vie de votre objet db de manière à ce qu'il vive au-delà de la méthode du contrôleur, soit apporter tous vos les données dans les objets du modèle en mémoire avant de les transmettre à la vue.

voir ici pour une explication similaire.

10
Mike Marshall

Une mauvaise pratique, mais vous pouvez définir

this.ContextOptions.LazyLoadingEnabled = false;

dans le constructor du Context

9
vothaison

Le problème est que vous émettez une copie superficielle lorsque vous effectuez:

 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
                };

Ce que vous devez faire est de créer un UsersCopy, puis de parcourir les utilisateurs en copiant les valeurs dans UsersCopy, puis de renvoyer UsersCopy pour effectuer une copie complète

Quelque chose comme

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);
1
Travis J

Si vous rencontrez des problèmes pour afficher la propriété enfant, c'est-à-dire les éléments de campagne. Voici la sale solution qui a fonctionné pour moi. Correction de mon problème de non-récupération des éléments enfants d'un objet:

header.MachineDataLines = header.MachineDataLines;

1
Andy Singh