Manchmal erlebt man als Entwickler seine Überraschungen. Mein heutiges Learning: kleine Änderungen haben eine große Auswirkung.
Aber der Reihe nach. Ich habe ein simples WebAPI Projekt das Daten aus einer Datenbank holt und intern aufbereitet, so dass eine geeignete Objektstruktur zurückgeliefert wird und ich in der JavaScript Anwendung nicht viel machen muss.
Im Code wird eine LINQ Abfrage ausgeführt und für jedes Element der Ergebnismenge wird in einer Schleife eine weitere LINQ Abfrage durchgeführt. D.h. von der äußeren Abfrage ist der Datareader offen und innerhalb der Schleife kann kein neuer geöffnet werden.
1 var header = from h in ctx.FeedbackSeminarFeedbackHeaders
2 where h.SeminarAppointmentID == AppointmentID
3 select h;
4
5 foreach(var fh in header)
6 {
7 FeedbackHeader hd = new FeedbackHeader()
8 {
9 Firma = fh.FirmenName,
10 Teilnehmer = fh.FirstName + " " + fh.LastName,
11 Datum = fh.Date.Value,
12 Anmerkung = fh.Note + " " + fh.Opinion,
13 Trainer = appointment.Trainer,
14 Ort=appointment.Location,
15 Seminar=appointment.Seminar
16 };
17 var fragen = from f in ctx.FeedbackSeminarFeedbackAnswers
18 where f.FeedbackID == fh.ID
19 orderby f.QuestionCategoryID, f.Sort
20 select f;
21
22 foreach(var fr in fragen)
23 {
24 hd.Fragen.Add(new FeedbackAnswer{
25 Frage = fr.Question,
26 Antwort=fr.Answer,
27 Sort = fr.Sort.Value
28 });
29 }
30 ret.Add(hd);
Die Fehlermeldung tritt in Zeile 22 auf.
Zu meiner heutigen Überraschung stellte ich fest, dass der Code lokal ausgeführt funktioniert aber wenn das Projekt auf Azure gehosted wird nicht mehr! Beide Varianten greifen auf die selbe Datenbank zu. Somit konnte ich Datenungleichheiten ausschließen.
Meine erste Überlegung war, dass Azure anders ist. Und zumal ich ja am Code nichts geändert habe, dieses Projekt bereits funktioniert hatte, kann es ja nur der “böse Azure-Admin” gewesen sein, der ein neues Update eingespielt hat.
Nichts von dem war es: Im Connectionstring fehlte der Eintrag: MultipleActiveResultSets=True;
In der lokalen Web.config Datei war er eingetragen, daher funktionierte der Code. In der Web.Config für Azure war zwar die selbe Datenbank angegeben, aber der Eintrag fehlte. Früher hat das Projekt aber funktioniert. Das ist leicht erklärt: vor ein paar Wochen wurde der SQL Server getauscht. Ich passte den Config Eintrag an, und dabei habe ich wohl den MultipleActiveResultSets-Eintrag überschrieben. Natürlich tritt der Fehler nur an einer wenig genutzten Funktion der Anwendung aus. Worauf er nicht gleich gesehen wurde…. usw. wir kennen das. Wieder mal ein Grund für umfangreiche UnitTests…
Geht es auch ohne MultipleActiveResultSets=True;?
Ja. Es muss nur sichergestellt werden, dass die LINQ Abfrage gleich komplett ausgeführt wird. Das kann man erreichen indem die Ergebnismenge gleich mit der Funktion .ToList() in eine neue Liste geschrieben wird. Dann ist der DataReader auch gleich wieder geschlossen und steht für die nächste Abfrage zu Verfügung.
Also sieht die Abfrage nun so aus:
1 var header = (from h in ctx.FeedbackSeminarFeedbackHeaders
2 where h.SeminarAppointmentID == AppointmentID
3 select h).ToList();