J'essaie de remplir un GridView
Entity Frameworkm en utilisant mais chaque fois que j'obtiens l'erreur suivante:
«L'accesseur de propriété 'LoanProduct' sur l'objet 'COSIS_DAL.MemberLoan' a levé l'exception suivante: l'instance ObjectContext a été supprimée et ne peut plus être utilisée pour les opérations qui nécessitent une connexion.»
Mon code est:
public List<MemberLoan> GetAllMembersForLoan(string keyword)
{
using (CosisEntities db = new CosisEntities())
{
IQueryable<MemberLoan> query = db.MemberLoans.OrderByDescending(m => m.LoanDate);
if (!string.IsNullOrEmpty(keyword))
{
keyword = keyword.ToLower();
query = query.Where(m =>
m.LoanProviderCode.Contains(keyword)
|| m.MemNo.Contains(keyword)
|| (!string.IsNullOrEmpty(m.LoanProduct.LoanProductName) && m.LoanProduct.LoanProductName.ToLower().Contains(keyword))
|| m.Membership.MemName.Contains(keyword)
|| m.GeneralMasterInformation.Description.Contains(keyword)
);
}
return query.ToList();
}
}
protected void btnSearch_Click(object sender, ImageClickEventArgs e)
{
string keyword = txtKeyword.Text.ToLower();
LoanController c = new LoanController();
List<COSIS_DAL.MemberLoan> list = new List<COSIS_DAL.MemberLoan>();
list = c.GetAllMembersForLoan(keyword);
if (list.Count <= 0)
{
lblMsg.Text = "No Records Found";
GridView1.DataSourceID = null;
GridView1.DataSource = null;
GridView1.DataBind();
}
else
{
lblMsg.Text = "";
GridView1.DataSourceID = null;
GridView1.DataSource = list;
GridView1.DataBind();
}
}
L'erreur mentionne la LoanProductName
colonne du Gridview
. Mentionné: J'utilise C #, ASP.net, SQL-Server 2008 comme DB back-end.
Je suis assez nouveau dans Entity Framework. Je ne comprends pas pourquoi j'obtiens cette erreur. Quelqu'un peut-il m'aider s'il-vous-plaît?
c#
asp.net
entity-framework
barsan
la source
la source
query.Include("SomeOtherTable")
db.MemberLoans.Include("LoanProduct").OrderByDescending()
vérifier la syntaxe car je n'ai pas de VS devant moi.db.MemberLoans.Include("LoanProduct").Include("SomeOtherTable)
. Vérifiez les réponses de @Tragedian et @lazyberezovskyRéponses:
Par défaut, Entity Framework utilise le chargement différé pour les propriétés de navigation. C'est pourquoi ces propriétés doivent être marquées comme virtuelles - EF crée une classe proxy pour votre entité et remplace les propriétés de navigation pour permettre le chargement différé. Par exemple, si vous avez cette entité:
Entity Framework retournera le proxy hérité de cette entité et fournira l'instance DbContext à ce proxy afin de permettre le chargement différé de l'appartenance plus tard:
Ainsi, l'entité a une instance de DbContext qui a été utilisée pour charger l'entité. C'est ton problème. Vous avez un
using
blocage autour de l'utilisation de CosisEntities. Qui supprime le contexte avant que les entités ne soient renvoyées. Lorsqu'un code essaie ultérieurement d'utiliser la propriété de navigation chargée différé, il échoue, car le contexte est supprimé à ce moment.Pour résoudre ce problème, vous pouvez utiliser le chargement hâtif des propriétés de navigation dont vous aurez besoin plus tard:
Cela préchargera toutes les adhésions et le chargement différé ne sera pas utilisé. Pour plus d'informations, consultez l' article Chargement des entités associées sur MSDN.
la source
db.MemberLoans.Include(m => m.Membership).Include(m => m.LoanProduct).OrderByDescending(m => m.LoanDate);
cela générera une requête JOIN et retournera toutes les données à la fois.La
CosisEntities
classe est à vousDbContext
. Lorsque vous créez un contexte dans unusing
bloc, vous définissez les limites de votre opération orientée données.Dans votre code, vous essayez d'émettre le résultat d'une requête à partir d'une méthode, puis de terminer le contexte dans la méthode. L'opération à laquelle vous transmettez le résultat essaie alors d'accéder aux entités afin de remplir la vue de grille. Quelque part dans le processus de liaison à la grille, une propriété à chargement différé est en cours d'accès et Entity Framework tente d'effectuer une recherche pour obtenir les valeurs. Il échoue, car le contexte associé est déjà terminé.
Vous avez deux problèmes:
Vous êtes des entités à chargement paresseux lorsque vous vous connectez à la grille. Cela signifie que vous effectuez de nombreuses opérations de requête distinctes sur SQL Server, ce qui va tout ralentir. Vous pouvez résoudre ce problème en rendant les propriétés associées chargées par défaut ou en demandant à Entity Framework de les inclure dans les résultats de cette requête à l'aide de la
Include
méthode d'extension.Vous terminez votre contexte prématurément: a
DbContext
devrait être disponible dans toute l'unité de travail en cours d'exécution, ne le supprimant que lorsque vous avez terminé avec le travail en cours. Dans le cas d'ASP.NET, une unité de travail est généralement la requête HTTP en cours de traitement.la source
Conclusion
Votre code a récupéré des données (entités) via une structure d'entité avec le chargement différé activé et une fois le DbContext supprimé, votre code fait référence à des propriétés (entités liées / relation / navigation) qui n'ont pas été explicitement demandées.
Plus précisement
Le
InvalidOperationException
avec ce message signifie toujours la même chose: vous demandez des données (entités) de entity-framework après que le DbContext a été supprimé.Un cas simple:
(ces classes seront utilisées pour tous les exemples de cette réponse et supposent que toutes les propriétés de navigation ont été configurées correctement et ont des tables associées dans la base de données)
La dernière ligne
InvalidOperationException
lèvera car le dbContext n'a pas désactivé le chargement différé et le code accède à la propriété de navigation Pet après que le contexte a été supprimé par l'instruction using.Débogage
Comment trouvez-vous la source de cette exception? En plus de regarder l'exception elle-même, qui sera lancée exactement à l'endroit où elle se produit, les règles générales de débogage dans Visual Studio s'appliquent: placez des points d'arrêt stratégiques et inspectez vos variables , soit en passant la souris sur leurs noms, en ouvrant un ( Rapide) Regardez la fenêtre ou en utilisant les différents panneaux de débogage comme Locals et Autos.
Si vous souhaitez savoir où se trouve ou non la référence, cliquez avec le bouton droit sur son nom et sélectionnez «Rechercher toutes les références». Vous pouvez ensuite placer un point d'arrêt à chaque emplacement qui demande des données et exécuter votre programme avec le débogueur attaché. Chaque fois que le débogueur s'arrête sur un tel point d'arrêt, vous devez déterminer si votre propriété de navigation doit avoir été remplie ou si les données demandées sont nécessaires.
Façons d'éviter
Désactiver le chargement différé
Avantages: au lieu de lancer l'exception InvalidOperationException, la propriété sera nulle. L'accès aux propriétés de null ou la tentative de modification des propriétés de cette propriété lèvera une NullReferenceException .
Comment demander explicitement l'objet en cas de besoin:
Dans l'exemple précédent, Entity Framework matérialisera l'animal en plus de la personne. Cela peut être avantageux car il s'agit d'un seul appel à la base de données. (Cependant, il peut également y avoir d'énormes problèmes de performances en fonction du nombre de résultats renvoyés et du nombre de propriétés de navigation demandées.Dans ce cas, il n'y aurait aucune pénalité de performances car les deux instances ne sont qu'un seul enregistrement et une seule jointure).
ou
Dans l'exemple précédent, Entity Framework matérialisera l'animal indépendamment de la personne en effectuant un appel supplémentaire à la base de données. Par défaut, Entity Framework suit les objets qu'il a récupérés de la base de données et s'il trouve des propriétés de navigation qui correspondent, il remplira automatiquement ces entités. Dans ce cas, comme le
PetId
sur l'Person
objet correspond àPet.Id
, Entity Framework affectera lePerson.Pet
à laPet
valeur récupérée, avant que la valeur ne soit affectée à la variable familière.Je recommande toujours cette approche car elle oblige les programmeurs à comprendre quand et comment le code demande des données via Entity Framework. Lorsque le code lève une exception de référence nulle sur une propriété d'une entité, vous pouvez presque toujours être sûr que vous n'avez pas explicitement demandé ces données.
la source
C'est une réponse très tardive mais j'ai résolu le problème en désactivant le chargement paresseux:
la source
Dans mon cas, je passais tous les modèles 'Users' à la colonne et il n'était pas mappé correctement, donc je viens de passer 'Users.Name' et cela l'a corrigé.
la source
La plupart des autres réponses indiquent un chargement impatient, mais j'ai trouvé une autre solution.
Dans mon cas, j'avais un objet EF
InventoryItem
avec une collection d'InvActivity
objets enfants.Et comme je tirais de la collection d'objets enfant au lieu d'une requête de contexte (avec
IQueryable
), leInclude()
fonction n'était pas disponible pour implémenter un chargement hâtif. Donc, à la place, ma solution était de créer un contexte à partir duquel j'ai utiliséGetLatestActivity()
etattach()
l'objet retourné:Ainsi, vous n'êtes pas coincé avec un chargement impatient.
la source
Si vous utilisez ASP.NET Core et que vous vous demandez pourquoi vous recevez ce message dans l'une de vos méthodes de contrôleur asynchrone, assurez-vous de renvoyer un
Task
plutôt quevoid
- ASP.NET Core supprime les contextes injectés.(Je poste cette réponse car cette question est en haut dans les résultats de recherche pour ce message d'exception et c'est un problème subtil - peut-être est-ce utile aux personnes qui recherchent sur Google.)
la source