42

Estoy tratando de usar el patrón de repositorio con EF4 usando VS2010.Genere clases de POCO en un proyecto diferente al proyecto con el modelo de Entity Framework

Para este fin estoy usando la generación de código POCO haciendo clic derecho en el diseñador del modelo de entidad y haciendo clic en Agregar elemento de generación de código. Luego selecciono la plantilla de POCO y obtengo mis clases.

Lo que me gustaría hacer es tener mi solución estructurada en proyectos separados para clases de Entidad (POCO) y otro proyecto para el modelo de entidad y el código de repositorio.

Esto significa que mi proyecto MVC podría usar las clases POCO para vistas fuertemente tipadas, etc. y no tener que saber sobre el repositorio o tener que hacer una referencia al mismo.

Para conectarlo todo, tendré otro proyecto separado con interfaces y usaré IoC.

Suena bien en mi cabeza, ¡simplemente no sé cómo generar las clases en su propio proyecto! Puedo copiarlos y luego cambiar los espacios de nombres en ellos, pero quería evitar el trabajo manual cada vez que cambio el esquema en el archivo db y quiero actualizar mi modelo.

Gracias

Respuesta

38

En realidad las plantillas T4 en EF 4.0 fueron diseñados con este escenario en mente :)

Hay 2 plantillas:

  • Uno para las propias entidades (es decir ModelName.tt)
  • Uno para el ObjectContext (es decir ModelName.Context.tt)

Debe colocar el archivo ModelName.tt en su proyecto POCO, y simplemente cambie la plantilla para que apunte al archivo EDMX en el proyecto consciente de la persistencia.

Suena raro, lo sé: ahora hay una dependencia, pero está en el tiempo de generación T4, ¡no en tiempo de compilación! Y eso debería estar bien? Debido a que el conjunto de POCO resultante todavía es completamente persistente ignorante.

Ver los pasos 5 & 6 de esto: http://blogs.msdn.com/adonet/pages/walkthrough-poco-template-for-the-entity-framework.aspx para más.

Esperanza esto ayuda

Alex

+0

Enlace a la página del blog msdn no encontrada –

+0

@AmrElgarhy Internet Archive to the rescue! Checkout [http://web.archive.org/web/20110609064124/http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity- framework.aspx] (http://web.archive.org/web/20110609064124/http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the -entity-framework.aspx) – natenho

+0

¡Usted señor es una leyenda! : D – MickyD

6

@ Nick,

  1. Para forzar la regeneración de las entidades POCO, sólo tiene que hacer clic derecho en el archivo principal .tt y seleccione "Ejecutar Herramienta personalizada ". Esto lo obligará a regenerar sus clases de POCO con sus cambios actualizados en el modelo .edmx.
  2. ¿Hay algún problema con seguir adelante y hacer clic derecho en el modelo y seleccionar "Generar base de datos desde modelo ..." aunque no genere necesariamente la base de datos? Es muy probable que se deshaga de su 'Error 11007 ...'.
  3. Creo que es equivalente a un "código detrás". No sé nada más que eso.

Otra cosa a tener en cuenta sobre el enlace que Alex dio. Una vez que moví mi principal.tt a un proyecto diferente, el archivo que se generó a partir del archivo ".Context.tt" no compilaría porque le faltaban referencias a los archivos POCO que estaban ubicados en un espacio de nombres diferente (porque quería que mi ObjectContext estuviera en un dominio diferente de mis archivos POCO). Tuve que modificar el archivo ".Context.tt" para tener un using Poco.Namespace (donde Poco.Namespace es el nombre del espacio de nombres donde se generaron los archivos POCO). Esto luego permitió que mi proyecto compilara.

Joel

+0

re: 2. Al compilar recibo ahora esta advertencia para cada entidad: 'Error 11007: la entidad tipo XXXX no está mapeada'. Esto puede estar relacionado con no haber generado la base de datos (?) Pero esto no sucedía antes del movimiento edité el edmx (usando un editor xml) para eliminar el mapeo que estaba allí (aunque me pareció perfecto), luego fui Regrese al diseñador y agregue la asignación usando la herramienta. –

+0

Tuve este * exacto * mismo problema con el archivo ".Context.tt" y quise agregar una declaración 'using' que funcionó. El problema es que el archivo se genera automáticamente. Si el modelo tiene que actualizarse, la declaración 'using' deberá eliminarse y volverse a agregar. ¿Alguna mejor manera de arreglar esto? – atconway

+0

No importa, acabo de entender esto después de mirar el enlace de Alex. Desplácese a la sección llamada ** 7. Cambie los espacios de nombres "Blogging.Context.tt" para que coincidan con "Entities" ** El ** Espacio de nombres de la herramienta personalizada ** en las propiedades de Context.tt puede actualizarse para decir 'MyProject.Model' y las referencias se resolverán. – atconway

1

He encontrado un error importante cuando se utiliza este enfoque combinado con proyectos y controles de datos dinámico. Básicamente, obtendrás un error.

"No se pudo determinar una MetaTable. No se pudo determinar una MetaTable para la fuente de datos 'EntityDataSource1' y no se pudo inferir una de la URL de solicitud. Asegúrese de que la tabla esté correlacionada con la fuente de las dats o que la el origen de datos se configura con un tipo de contexto y un nombre de tabla válidos, o que la solicitud es parte de un DynamicDataRoute registrado. "

3

Para EF5 + Db Generador de contexto: es fácil mover su Name.Context.tt a un proyecto diferente. Sin embargo, deberá hacer referencia a las clases modelo. Puede hacerlo manualmente, pero esto requerirá que lo cambie cada vez que se genere el código. También podría usar el mismo espacio de nombres para ambos proyectos. Esto es válido y funcionará, pero creo que es un mal diseño. Otra alternativa es cambiar la plantilla T4 (Name.Context.tt).

modificarla (línea 43):

using System; 
using System.Data.Entity; 
using System.Data.Entity.Infrastructure; 
<# 
if (container.FunctionImports.Any()) 
{ 
#> 

A esto:

using System; 
using System.Data.Entity; 
using System.Data.Entity.Infrastructure; 
<# 
if (modelNamespace != codeNamespace) 
#> 
using <#=code.EscapeNamespace(modelNamespace)#>; 
<# 
if (container.FunctionImports.Any()) 
{ 
#> 

Esto comprobará si su espacio de nombres modelo difiere de su espacio de nombres de código, si es así, se insertará la necesaria usando para hacer referencia a tus clases modelo.

Cuestiones relacionadas