2012-05-10 33 views
14

The specified cast from a materialized 'System.Guid' type to the 'System.Int32' type is not valid.El reparto especificada de un tipo materializado 'System.Guid' al tipo 'System.Int32' no es válido

Tenemos varios servicios WCF que tienen modalidad de simultaneidad de múltiples y InstanceContextMode de individual. Nuestra arquitectura se centra en un modelo débilmente acoplado que utiliza la inyección de dependencia basada en el constructor. Esto, a su vez, se implementa utilizando Unity 2.0 (web.config de cada servicio tiene asignaciones entre interfaces y tipos definidos en una sección de contenedores de unidades). Una de nuestras dependencias es un ensamblado DAL (capa de acceso a datos) que usa Entity Framework 4 para comunicarse con el servidor MSSql. Las clases que hablan con la base de datos también se incluyen en el mapeo unitario.

Todo es genial cuando ejecutamos nuestras pruebas de integración. Pero cuando nos movemos a nuestro medio ambiente rendimiento para ejecutar las pruebas de carga (2, 3, 4 usuarios simultáneos) que comencemos a ver el siguiente error:

System.InvalidOperationException: The 'auth_token' property on 'Session' could not be set to a 'Int32' value. You must set this property to a non-null value of type 'Guid'.

Con la pila siguiente:

at System.Data.Common.Internal.Materialization.Shaper.ErrorHandlingValueReader`1.GetValue(DbDataReader reader, Int32 ordinal) 
at System.Data.Common.Internal.Materialization.Shaper.GetPropertyValueWithErrorHandling[TProperty](Int32 ordinal, String propertyName, String typeName) 
at lambda_method(Closure , Shaper) 
at System.Data.Common.Internal.Materialization.Shaper.HandleEntityAppendOnly[TEntity](Func`2 constructEntityDelegate, EntityKey entityKey, EntitySet entitySet) 
at lambda_method(Closure , Shaper) 
at System.Data.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper shaper) 
at System.Data.Common.Internal.Materialization.Shaper`1.SimpleEnumerator.MoveNext() 
at System.Linq.Enumerable.First[TSource](IEnumerable`1 source) 
at System.Linq.Queryable.First[TSource](IQueryable`1 source) 
at MISoa.DataAccessLayer.Authentication.AuthenticationDB.RetrieveSession(Guid authToken) 
at MISoa.DataAccessLayer.Authentication.AuthenticationAccess.RetrieveSession(String sessionToken) 

Aquí es el método culpable:

public Session RetrieveSession(Guid authToken) 
    { 
     CheckDBContext(); 
     var sessions = (from r in _dbContext.Sessions 
       where r.auth_token == authToken 
       select r); 
     return sessions.Count() > 0 ? sessions.First() : null; 
    } 

CheckDBContext método simplemente comprueba si el contexto db es nula y, si lo es, se lanza una excep personalizada ción.

El objeto de entidad Sesión emdx tiene estas propiedades comunes:

Guid auth_token 
DateTime time_stamp 
String user_id 
String app_id 

Por lo tanto, parece que a veces el linq anterior devuelve algún otro objeto de la base de datos en la primera columna es un int y no un guid? Y si es así, ¿por qué? ¿Tengo un problema con varios hilos que anulan el contexto db de los demás? Por cierto, resumimos el código que crea una instancia del contexto db en una clase separada (BaseDB) que también es manejada por unity. Entonces, como el servicio es singleton, tengo una instancia de BaseDB para todos, ¿verdad? ¿Este es el problema aquí?

Oh, una cosa más. Nos dijeron que tendremos MSSql 2005, entonces en el archivo edmx tenemos ProviderManifestToken="2005". Pero acabo de verificar y el servidor con nuestra base de datos de rendimiento es la versión 2008. ¿Es esto un problema?

Gracias por su ayuda.

+0

Las primeras cosas simples que verificaría: ¿es auth_token un Guid en su base de datos? El error dice que algo está intentando establecer session.auth_token en un int. ¿Hay una columna int Id que no esté asignada correctamente?¿Puede hacer un rastreo de perfiles sql e identificar la llamada sql real que se realiza? Realmente dudo que el multi-threading esté causando sus problemas aquí. –

+0

¿Está seguro de que la columna en la base de datos es del tipo de propiedad correspondiente? La excepción dice que el DbDataReader lee Guid pero la propiedad en su clase es int. – Pawel

Respuesta

2

Do I have a problem with multiple threads overriding each other's db context?

Sí. Ver aquí: http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx

Presupuesto de la caja grande de color amarillo en el siguiente enlace:

The ObjectContext class is not thread safe. The integrity of data objects in an ObjectContext cannot be ensured in multithreaded scenarios.

Es posible que desee considerar la posibilidad de [ThreadStaticAttribute] en su campo _dbContext.

+1

Así que el problema principal es que ObjectContext no es Threadsafe, eso está bien, pero solo quería mencionar que hacer que la propiedad DbContext Threadstatic pueda causar más problemas cuando se usa en WCF/Asp.Net, dependiendo del Host y cómo (o mejor cuando) Inicializas la propiedad. Por ejemplo, al usar WCF, debe usar OperationContext para almacenar estos elementos, ya que el Thread que está aceptando la solicitud puede no ser el mismo Thread que lo está ejecutando. vea [operationcontext] (http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontext.aspx). –

+0

@Bernhard Kircher: muy bien - ¡buen punto! – RobSiklos

0

Sospecho que su problema surge cuando no hay resultados, y se usa un valor nulo == 0 para la comparación del campo Guid en algún lugar del SQL generado. Intente hacer la comparación como una cadena (.ToString() en ambos) y vea si puede detectar el caso que está causando su problema.

Cuestiones relacionadas