La operación podría desestabilizar el tiempo de ejecución?

Estoy teniendo problemas para entender cuál es el problema aquí. Tengo un poco de código que extrae registros de una base de datos utilizando LINQ y los coloca en un objeto que se envía a una interfaz. Se parece un poco a esto:

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

Cuando pruebo esto, pongo el IEnumerable devuelto en una variable llamada resultados y ejecuto esta línea:

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

Cuando se ejecuta esto, obtengo una System.Security.VerificationException: “La operación podría desestabilizar el tiempo de ejecución”.

Encontré la solución aquí , que es esta:

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

Esto funciona, pero estoy teniendo problemas para entender lo que está sucediendo aquí. ¿Por qué obtuve la excepción en primer lugar y cómo las arreglaron las líneas de código anteriores? La documentación de MSDN parece sugerir que se trata de una cuestión de seguridad de tipo, pero no veo dónde estaba el tipo de código anterior, inseguro.

ACTUALIZAR Un poco más de información que descubrí. El primer ejemplo funciona si hago el tipo de retorno IQueryable. Esto arroja un poco más de luz sobre lo que estaba pasando mal, pero todavía estoy confundido sobre el por qué . ¿Por qué el comstackdor no me obligó a convertir el IEnumerable en un IQueryable?

Creo que es un problema de covarianza o contravarianza como se señala en esta publicación del foro .

Ver Covarianza y Contravarianza en C #, Parte Dos: Covarianza en Matriz y el rest de la serie de Covarianza y Contravarianza en el blog de Eric Lippert.

A pesar de que está tratando con Arrays en el artículo que relacioné, creo que aquí se presenta un problema similar. Con su primer ejemplo, está devolviendo un IEnumerable que podría contener objetos que implementan una interfaz que es más grande que ISomeTable (es decir, podría poner una Tortuga en un Animal IEnumerable cuando ese IEnumerable solo pueda contener Jirafas). Creo que la razón por la que funciona cuando devuelves IQueryable es porque es más grande / más ancha que cualquier otra cosa que puedas devolver, por lo que tienes garantizado que lo que devuelvas podrás manejar (?).

En el segundo ejemplo, OfType garantiza que lo que se devuelve es un objeto que almacena toda la información necesaria para devolver solo los elementos que se pueden enviar a Giraffe.

Estoy bastante seguro de que tiene algo que ver con los problemas de seguridad tipo descritos anteriormente, pero como Eric Lippert dice Funciones de orden superior, hiere a mi cerebro y tengo problemas para express con precisión por qué esto es un problema co / contravariante.

Encontré esta entrada mientras buscaba mi propia solución para “la operación podría desestabilizar el tiempo de ejecución”. Mientras que la sugerencia de covarianza / contravariancia anterior parece muy interesante, al final encontré que obtengo el mismo mensaje de error ejecutando mis pruebas unitarias con cobertura de código activada y el atributo de ensamblado AllowPartiallyTrustedCallers establecido.

Eliminar el atributo AllowPartiallyTrustedCallers provocó que mis pruebas se ejecutaran correctamente. También pude desactivar la cobertura del código para que se ejecutaran, pero esa no era una solución aceptable.

Con suerte, esto ayuda a alguien más que llega a esta página a tratar de encontrar una solución a este problema.

Solo una suposición, pero el operador como puede devolver un valor nulo, por lo que puede tener que ver con la implementación real del new SomeObject { ... } , ya que es azúcar sintáctica. Los return results.OfType(); filtros basados ​​en el tipo, por lo que la statement de devolución de su método solo devolverá ese tipo (asegurando la seguridad del tipo). Me encontré con un problema similar con la devolución de tipos generics.

PD: Me encanta la “Operación podría desestabilizar el tiempo de ejecución”. excepción. Eso es casi como la excepción “Usted podría volar el Internet”.

Encontré este error con un código similar;

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

Este código aparentemente inofensivo era parte de un método UserControl que se llamó desde una página. No hay problema en un entorno de desarrollo .NET4, sin embargo, cuando el sitio fue precomstackdo e implementado en el servidor en .NET3.5, recibí este error.

Sospecho que esto tiene algo que ver con el hecho de que el control se estaba comstackndo en una DLL separada combinada con los cambios de seguridad entre los marcos como se describe en este blog de seguridad .NET

Mi solución: ejecutar el sitio en vivo en .NET4

¿Todavía falla si cambia esto?

 select new SomeObject { ... } as ISomeTable; 

a esto:

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

?

Si es así (como veo que has confirmado), ¿quizás esto tiene que ver con el hecho de que una implementación de interfaz podría ser una clase o una estructura? ¿El problema todavía aparece si seleccionas una clase abstracta en lugar de una interfaz?

Descubrí que OfType tenía algunos efectos secundarios desagradables al usar linq en sql. Por ejemplo, las partes del linq que se evaluaron previamente después de que la consulta se ejecutó contra el db se tradujeron en cambio a SQL. Esto falló ya que esas secciones no tenían equivalente SQL. Terminé utilizando .Cast en su lugar, que parece resolver el problema también.

En mi caso, había declarado erróneamente la propiedad de Almacenamiento en el atributo Columna de una clase Linq2SQL

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

Tuve el mismo problema, pero con la herencia definí una clase en el conjunto A y una subclase en el conjunto B después de agregar el atributo siguiente al ensamblado A, problema resuelto:

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

Me encontré con este error al utilizar la biblioteca pasiva “Marco de acceso a datos dynamics”. El origen del error fue la línea 100 en el archivo DynamicDatabase.cs.

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

Cambié esa línea de código a:

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

Al hacerlo, resolvió el problema. Seguí adelante y bifurqué el proyecto y envié el cambio al autor original.

Gracias, Jason Baker, por señalar la solución en su pregunta original.

En una nota lateral, la biblioteca original funcionó bien en mi máquina local y en un VPS de Rackspace, pero cuando presioné el mismo código para un entorno de alojamiento compartido (GoDaddy y Rackspace’s Cloud Sites), comencé a obtener la “Operación podría desestabilizar el tiempo de ejecución “error.

Supongo que es posible que Linq to Sql no sea compatible con la conversión cuando se traduce a SQL.