En mi tabajo tenemos una base de datos para controlar las horas de dedicación del personal a los distintos proyectos, que en el entorno de desarrollo se tiene en un SQL Server 2005, pero en el servidor de producción está aún en 2000.
Cuando se planteó realizar cienta nueva funcionalidad sobre esta base de datos, ni cortos ni perezosos nos metimos a hacerlo con VS 2010 y EF 4. En el entorno de desarrollo todo fue miel sobre hojuelas, pero cuando lo pasamos a producción nos encontramos con este hermoso error:
"An error occurred while executing the command definition. See the inner exception for details."
Mirando la excepción original, y usando intellitrace, nos encontramos con que EF 4 genera código SQL que no es válido para SQL Server 2000. En concreto, esta sentencia de LINQ:
Usuario primer = (from Usuario u in ctx.Usuarios
orderby u.NomUsu
select u).FirstOrDefault();
Genera la siguiente sentencia SQL:
SELECT TOP (1)
[Extent1].[IDUsu] AS [IDUsu],
[Extent1].[NomUsu] AS [NomUsu],
.
.
.
FROM (SELECT
[Usuario].[IDUsu] AS [IDUsu],
.
.
.
FROM [dbo].[Usuario] AS [Usuario]) AS [Extent1]
ORDER BY [Extent1].[NomUsu] ASC
En concreto, el problema de esta sentencia es la forma en la que se ha generado el "top", ya que usa paréntesis, y en sql server 2005 si es válida, pero en sql 2000 debe realizarse sin paréntesis:
SELECT TOP 1...
Parece que lo tenemos mal, porque sin los métodos First() o FirstOrDefault() las sentencias de LINQ se complican, ya que habría que recuperar colecciones completas. Y no hablemos de las paginaciones, ya que este mismo problema se produce con el método Take().
¿Cómo se puede solucinar este problema? Pues Microsoft no da soporte de SQL Server 2000 en las herramientas de EF 4 (el diseñador, por ejemplo), pero el runtime si que tiene soporte de SQL 2000. Para hacer que nuestro modelo de entidades genere código válido para SQL 2000 tenemos que cambiar el XML del fichero edmx. Para ello, en VS 2010 hacemos clic con el botón derecho en el fichero edmx, y elegimos "Open with..." y "XML (Text) Editor". Esto abrirá el fichero como si de cualquier XML se tratara. Buscamos el elemento "edmx:Runtime", dentro de este, el "edmx:StorageModels", y dentro de este, el elemento "Schema". En este elemento, buscamos el atributo "ProviderManifestToken", y cambiamos su valor, que será 2005 o 2008 en función de la versión que usemos en desarrollo, a "2000". Quedaría algo así:
<Schema Namespace="DSTTSModel.Store" Alias="Self"
Provider="System.Data.SqlClient" ProviderManifestToken="2000"
xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
¡Voilá! Si compilamos y ejecutamos ya no nos aparece el error en tiempo de ejecución.
Esto no quiere decir que TODO lo que se puede hacer con LINQ + EF 4 se pueda hacer en SQL Server 2000, pero hemos salvado el primer escollo, y no uno pequeño.
No hay comentarios:
Publicar un comentario