it-swarm.com.de

Betrieb könnte die Laufzeit destabilisieren?

Ich habe ein bisschen Schwierigkeiten zu verstehen, was das Problem hier ist. Ich habe ein bisschen Code, der mithilfe von LINQ Datensätze aus einer Datenbank abruft und sie in ein Objekt einfügt, das in eine Schnittstelle umgewandelt wird. Es sieht ein bisschen so aus:

public IEnumerable<ISomeObject> query()
{
    return from a in dc.SomeTable
           select new SomeObject
           {
             //Assign various members here
           } as ISomeObject;
}

Wenn ich dies teste, habe ich den zurückgegebenen IEnumerable in eine Variable namens results gestellt und diese Zeile ausgeführt:

Assert.AreEqual(EXPECTED_COUNT, results.Count());

Wenn dies ausgeführt wird, erhalte ich eine System.Security.VerificationException: "Die Operation konnte die Laufzeit destabilisieren."

Ich habe die Lösung hier gefunden, die Folgendes ist:

var results = from a in dc.SomeTable
              select new SomeObject
              {
                //Assign various members here
              } as ISomeTable;
return results.OfType<ISomeObject>();

Das funktioniert, aber ich habe Probleme zu verstehen, was hier passiert. Warum habe ich die Ausnahme überhaupt bekommen und wie wurde sie durch die obigen Codezeilen behoben? Die MSDN-Dokumentation scheint darauf hinzudeuten, dass es sich hierbei um eine Typensicherheit handelt, aber ich kann nicht erkennen, wo der vorherige Code typ-unsicher war.

UPDATE Ein bisschen mehr Informationen habe ich herausgefunden. Das erste Beispiel funktioniert, wenn ich den Rückgabetyp IQueryable mache. Dies wirft ein wenig mehr Licht auf was lief schief, aber ich bin immer noch verwirrt über die warum. Warum zwang mich der Compiler nicht, das IEnumerable in ein IQueryable umzuwandeln?

37
Jason Baker

Ich glaube, es handelt sich um eine Frage der Kovarianz oder der Widersprüchlichkeit, wie von diesem Forenbeitrag festgestellt.

Siehe Kovarianz und Kontravarianz in C #, Zweiter Teil: Array Kovarianz und den Rest der Kovarianz- und Kontravarianz-Serie in Eric Lipperts Blog.

Obwohl er sich in dem Artikel, den ich verlinkt habe, mit Arrays befasst, ist meiner Ansicht nach ein ähnliches Problem hier. In Ihrem ersten Beispiel geben Sie eine IEnumerable zurück, die Objekte enthalten könnte, die eine Schnittstelle implementieren, die größer als ISomeTable ist (d. H. - Sie könnten eine Turtle in ein Animals IEnumerable einfügen, wenn dieses IEnumerable nur Giraffen enthalten kann). Ich denke, der Grund, warum es funktioniert, wenn Sie IQueryable zurückgeben, liegt darin, dass größer/breiter ist als alles, was Sie zurückgeben könnten. Sie können also sicher sein, dass das, was Sie zurückgeben, in der Lage ist (?).

Im zweiten Beispiel stellt OfType sicher, dass das Objekt, das zurückgegeben wird, alle Informationen speichert, die erforderlich sind, um nur die Elemente zurückzugeben, die an Giraffe übertragen werden können.

Ich bin mir ziemlich sicher, dass es etwas mit den oben skizzierten Problemen der Typsicherheit zu tun hat, aber wie Eric Lippert sagt Höhere Ordnungsfunktionen schaden meinem Gehirn und ich habe Mühe zu sagen, warum dies ein Co/Contravariant-Problem ist.

19
Grant Wagner

Ich habe diesen Eintrag gefunden, als ich nach meiner eigenen Lösung gesucht habe, um "die Laufzeit zu destabilisieren". Während der oben genannte Hinweis zu Kovarianz/Kontra-Varianz sehr interessant aussieht, habe ich am Ende herausgefunden, dass ich dieselbe Fehlermeldung bekomme, wenn ich Unit-Tests mit aktivierter Codeabdeckung und dem AllowPartiallyTrustedCallers Assembly-Attributset ausführte. 

Durch das Entfernen des AllowPartiallyTrustedCallers-Attributs liefen meine Tests einwandfrei. Ich konnte auch die Codeabdeckung deaktivieren, um sie zum Laufen zu bringen, aber das war keine akzeptable Lösung.

Hoffentlich hilft dies jemandem, der es auf diese Seite schafft, eine Lösung für dieses Problem zu finden.

14
Ira Miller

Nur eine Vermutung, aber der Operator as gibt möglicherweise eine Null zurück - daher kann es mit der tatsächlichen Implementierung des new SomeObject { ... }-Codes zu tun haben, da es sich um syntaktischen Zucker handelt. Da return results.OfType<ISomeTable>(); nach Typ filtert, gibt die Rückgabeanweisung Ihrer Methode nur diesen Typ zurück (gewährleistet die Typensicherheit). Ich habe ein ähnliches Problem mit der Rückgabe generischer Typen.

P.S. Ich liebe die "Operation könnte die Laufzeit destabilisieren." Ausnahme. Das ist fast wie die Ausnahme "Sie könnten das Internet in die Luft jagen".

5
Zachary Yates

Ich bin auf diesen Fehler mit ähnlichem Code gestoßen;

IEnumerable<Table> records = (from t in db.Tables
                              where t.Id.Equals(1)
                              select t).ToList();

Dieser scheinbar harmlose Code war Teil einer UserControl-Methode, die von einer Page aus aufgerufen wurde. Kein Problem in einer .NET4-Entwicklungsumgebung. Als die Site vorkompiliert und auf .NET3.5 auf dem Server bereitgestellt wurde, erhielt ich diesen Fehler.

Ich vermute, das hat etwas damit zu tun, dass das Steuerelement in einer separaten DLL zusammen mit den Sicherheitsänderungen zwischen den Frameworks kompiliert wurde, wie in diesem .NET-Sicherheitsblog beschrieben.

Meine Lösung: Führen Sie die Live-Site unter .NET4 aus

2
Red Taz

Ich hatte das gleiche Problem, aber mit Vererbung Ich definierte eine Klasse in Assembly A und eine Unterklasse in Assembly B Nachdem ich unten in der Assembly A ein Attribut hinzugefügt hatte, wurde das Problem gelöst:

[Assembly: SecurityRules(SecurityRuleSet.Level1, SkipVerificationInFullTrust = true)]
0

Ich habe festgestellt, dass OfType bei der Verwendung von linq to sql einige unangenehme Nebenwirkungen hatte. Beispielsweise wurden Teile der Linq, die zuvor ausgewertet wurden, nachdem die Abfrage in der Datenbank ausgeführt wurde, stattdessen in SQL übersetzt. Dies schlug fehl, da diese Abschnitte keine SQL-Entsprechung hatten. Am Ende habe ich stattdessen .Cast verwendet, was auch das Problem zu lösen scheint.

0
LaserJesus

Schlägt es immer noch fehl, wenn Sie dies ändern:

select new SomeObject { ... } as ISomeTable;

zu diesem:

select (ISomeTable) new SomeObject { ... };

?

Wenn ja (wie ich sehe, haben Sie bestätigt), hat dies vielleicht damit zu tun, dass eine Schnittstellenimplementierung entweder eine Klasse oder eine Struktur sein könnte. Tritt das Problem weiterhin auf, wenn Sie eine abstrakte Klasse und keine Schnittstelle verwenden?

0
Av Pinzur

Dieser Fehler ist bei der Verwendung des "Dynamic Data Access Framework" Passive Library aufgetreten. Die Fehlerquelle war Zeile 100 in der Datei DynamicDatabase.cs.

databaseDetectors = (databaseDetectors ?? Enumerable.Empty<DatabaseDetector>()).DefaultIfEmpty(new DatabaseDetector());

Ich habe diese Codezeile geändert in:

databaseDetectors = (databaseDetectors ?? Enumerable.Empty<DatabaseDetector>()).DefaultIfEmpty(new DatabaseDetector()).OfType<IDatabaseDetector>();

Dadurch wurde das Problem gelöst. Ich ging weiter und gab das Projekt ab und reichte die Änderung beim ursprünglichen Autor ein.

Vielen Dank, Jason Baker, dass Sie in Ihrer ursprünglichen Frage auf die Lösung hingewiesen haben.

Nebenbei bemerkt, die Originalbibliothek lief gut auf meinem lokalen Rechner und auf einem Rackspace-VPS, aber als ich denselben Code in eine gemeinsam genutzte Hosting-Umgebung (GoDaddy und Rackspace Cloud-Sites) übertrug, begann ich mit der "Operation konnte die Laufzeit destabilisieren " Error.

0
Tod Birdsall

In meinem Fall hatte ich die Storage-Eigenschaft im Column-Attribut einer Linq2SQL-Klasse falsch deklariert 

    [Column(Storage = "_Alias", DbType = "NVarChar(50)")]
    public string UserAlias
0
user1760527