Ich versuche, ein GridView
mit Entity Frameworkm zu füllen, aber jedes Mal erhalte ich den folgenden Fehler:
"Der Eigenschaftenzugriff 'LoanProduct' für das Objekt 'COSIS_DAL.MemberLoan' hat die folgende Ausnahme ausgelöst: Die ObjectContext-Instanz wurde entsorgt und kann nicht mehr für Vorgänge verwendet werden, für die eine Verbindung erforderlich ist."
Mein Code lautet:
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();
}
}
Der Fehler erwähnt die LoanProductName
Spalte der Gridview
. Erwähnt: Ich verwende C #, ASP.net, SQL-Server 2008 als Back-End-Datenbank.
Ich bin ziemlich neu in Entity Framework. Ich kann nicht verstehen, warum ich diesen Fehler erhalte. Kann mir bitte jemand helfen?
c#
asp.net
entity-framework
Barsan
quelle
quelle
query.Include("SomeOtherTable")
db.MemberLoans.Include("LoanProduct").OrderByDescending()
die Syntax überprüfen , weil ich VS vor mir nicht haben.db.MemberLoans.Include("LoanProduct").Include("SomeOtherTable)
. Überprüfen Sie die Antworten von @Tragedian und @lazyberezovskyAntworten:
Standardmäßig verwendet Entity Framework das verzögerte Laden für Navigationseigenschaften. Aus diesem Grund sollten diese Eigenschaften als virtuell markiert werden. EF erstellt eine Proxy-Klasse für Ihre Entität und überschreibt die Navigationseigenschaften, um ein verzögertes Laden zu ermöglichen. ZB wenn Sie diese Entität haben:
Das Entity Framework gibt den von dieser Entität geerbten Proxy zurück und stellt diesem Proxy die DbContext-Instanz zur Verfügung, um später ein verzögertes Laden der Mitgliedschaft zu ermöglichen:
Die Entität verfügt also über eine Instanz von DbContext, die zum Laden der Entität verwendet wurde. Das ist dein Problem. Sie haben
using
die Verwendung von CosisEntities blockiert. Womit der Kontext gelöscht wird, bevor Entitäten zurückgegeben werden. Wenn ein Code später versucht, eine verzögert geladene Navigationseigenschaft zu verwenden, schlägt dies fehl, da der Kontext in diesem Moment verfügbar ist.Um dieses Verhalten zu beheben, können Sie die Navigationseigenschaften, die Sie später benötigen, eifrig laden:
Dadurch werden alle Mitgliedschaften vorab geladen, und das verzögerte Laden wird nicht verwendet. Weitere Informationen finden Sie im Artikel Laden verwandter Entitäten in MSDN.
quelle
db.MemberLoans.Include(m => m.Membership).Include(m => m.LoanProduct).OrderByDescending(m => m.LoanDate);
generiert beispielsweise eine JOIN-Abfrage und gibt alle Daten auf einmal zurück.Die
CosisEntities
Klasse ist deineDbContext
. Wenn Sie einen Kontext in einemusing
Block erstellen , definieren Sie die Grenzen für Ihre datenorientierte Operation.In Ihrem Code versuchen Sie, das Ergebnis einer Abfrage von einer Methode auszugeben und dann den Kontext innerhalb der Methode zu beenden. Die Operation, an die Sie das Ergebnis übergeben, versucht dann, auf die Entitäten zuzugreifen, um die Rasteransicht zu füllen. Irgendwann beim Binden an das Raster wird auf eine verzögert geladene Eigenschaft zugegriffen, und Entity Framework versucht, eine Suche durchzuführen, um die Werte abzurufen. Es schlägt fehl, da der zugehörige Kontext bereits beendet wurde.
Sie haben zwei Probleme:
Sie laden Entitäten faul, wenn Sie an das Raster binden. Dies bedeutet, dass Sie viele separate Abfragevorgänge für SQL Server ausführen, die alles verlangsamen. Sie können dieses Problem beheben, indem Sie entweder die zugehörigen Eigenschaften standardmäßig eifrig laden oder Entity Framework auffordern, sie mithilfe der
Include
Erweiterungsmethode in die Ergebnisse dieser Abfrage aufzunehmen .Sie beenden Ihren Kontext vorzeitig: a
DbContext
sollte in der gesamten ausgeführten Arbeitseinheit verfügbar sein und erst dann verfügbar sein, wenn Sie mit der vorliegenden Arbeit fertig sind. Im Fall von ASP.NET ist eine Arbeitseinheit normalerweise die HTTP-Anforderung, die verarbeitet wird.quelle
Endeffekt
Ihr Code hat Daten (Entitäten) über das Entitätsframework mit aktiviertem verzögertem Laden abgerufen. Nachdem der DbContext entsorgt wurde, verweist Ihr Code auf Eigenschaften (verwandte / Beziehungs- / Navigationsentitäten), die nicht explizit angefordert wurden.
Genauer
Das
InvalidOperationException
mit dieser Nachricht bedeutet immer dasselbe: Sie fordern Daten (Entitäten) vom Entity-Framework an, nachdem der DbContext entsorgt wurde.Ein einfacher Fall:
(Diese Klassen werden für alle Beispiele in dieser Antwort verwendet und setzen voraus, dass alle Navigationseigenschaften korrekt konfiguriert wurden und Tabellen in der Datenbank zugeordnet sind.)
In der letzten Zeile wird
InvalidOperationException
das ausgegeben, da der dbContext das verzögerte Laden nicht deaktiviert hat und der Code auf die Pet-Navigationseigenschaft zugreift, nachdem der Kontext durch die using-Anweisung entsorgt wurde.Debuggen
Wie finden Sie die Quelle dieser Ausnahme? Abgesehen von der Betrachtung der Ausnahme selbst, die genau an der Stelle ausgelöst wird, an der sie auftritt, gelten die allgemeinen Regeln für das Debuggen in Visual Studio: Platzieren Sie strategische Haltepunkte und überprüfen Sie Ihre Variablen , indem Sie entweder mit der Maus über deren Namen fahren und ein ( Schnell) Beobachten Sie das Fenster oder verwenden Sie die verschiedenen Debugging-Bereiche wie Locals und Autos.
Wenn Sie herausfinden möchten, wo die Referenz festgelegt ist oder nicht, klicken Sie mit der rechten Maustaste auf den Namen und wählen Sie "Alle Referenzen suchen". Sie können dann an jedem Speicherort, an dem Daten angefordert werden, einen Haltepunkt setzen und Ihr Programm mit dem angehängten Debugger ausführen. Jedes Mal, wenn der Debugger an einem solchen Haltepunkt unterbrochen wird, müssen Sie feststellen, ob Ihre Navigationseigenschaft ausgefüllt werden sollte oder ob die angeforderten Daten erforderlich sind.
Möglichkeiten zu vermeiden
Lazy-Loading deaktivieren
Vorteile: Anstatt die InvalidOperationException auszulösen, ist die Eigenschaft null. Wenn Sie auf Eigenschaften von null zugreifen oder versuchen, die Eigenschaften dieser Eigenschaft zu ändern, wird eine NullReferenceException ausgelöst .
So fordern Sie das Objekt bei Bedarf explizit an:
Im vorherigen Beispiel materialisiert das Entity Framework das Haustier zusätzlich zur Person. Dies kann vorteilhaft sein, da es sich um einen einzelnen Aufruf der Datenbank handelt. (Abhängig von der Anzahl der zurückgegebenen Ergebnisse und der Anzahl der angeforderten Navigationseigenschaften kann es jedoch auch zu großen Leistungsproblemen kommen. In diesem Fall würde es keine Leistungseinbußen geben, da beide Instanzen nur ein einzelner Datensatz und ein einzelner Join sind.)
oder
Im vorherigen Beispiel materialisiert Entity Framework das Haustier unabhängig von der Person, indem es die Datenbank zusätzlich aufruft. Standardmäßig verfolgt Entity Framework Objekte, die aus der Datenbank abgerufen wurden, und füllt diese Entitäten automatisch auf magische Weise, wenn passende Navigationseigenschaften gefunden werden . In diesem Fall , da die
PetId
auf demPerson
Objekt entspricht dasPet.Id
wird Entity Framework zuweisen diePerson.Pet
auf denPet
Wert abgerufen, bevor der Wert für das Haustier Variablen zugewiesen wird.Ich empfehle diesen Ansatz immer, da er Programmierer dazu zwingt zu verstehen, wann und wie Code Daten über Entity Framework anfordert. Wenn Code eine Nullreferenzausnahme für eine Eigenschaft einer Entität auslöst, können Sie fast immer sicher sein, dass Sie diese Daten nicht explizit angefordert haben.
quelle
Es ist eine sehr späte Antwort, aber ich habe das Problem behoben, durch das das verzögerte Laden deaktiviert wurde:
quelle
In meinem Fall habe ich alle Modelle 'Benutzer' an die Spalte übergeben und es wurde nicht richtig zugeordnet, also habe ich nur 'Benutzer.Name' übergeben und es wurde behoben.
quelle
Die meisten anderen Antworten deuten auf eifriges Laden hin, aber ich habe eine andere Lösung gefunden.
In meinem Fall hatte ich ein EF-Objekt
InventoryItem
mit einer Sammlung vonInvActivity
untergeordneten Objekten.Und da ich anstelle einer Kontextabfrage (mit
IQueryable
) aus der untergeordneten Objektsammlung gezogen habe , war dieInclude()
Funktion nicht verfügbar, um eifriges Laden zu implementieren. Anstatt also war meine Lösung , die einen Zusammenhang von zu schaffen , wo ich genutztGetLatestActivity()
undattach()
das zurückgegebene Objekt:So bleiben Sie nicht beim eifrigen Laden hängen.
quelle
Wenn Sie ASP.NET Core verwenden und sich fragen, warum diese Meldung in einer Ihrer asynchronen Controller-Methoden angezeigt wird, stellen Sie sicher, dass Sie einen
Task
nichtvoid
- ASP.NET Core zurückgeben, der injizierte Kontexte bereitstellt.(Ich poste diese Antwort, da diese Frage in den Suchergebnissen zu dieser Ausnahmemeldung hoch ist und ein subtiles Problem darstellt. Vielleicht ist sie für Leute nützlich, die Google dafür verwenden.)
quelle