anotación estructural - agradable. Es la primera vez que escucho sobre esta característica, pero funciona. Lo intenté. Trataré de explicarlo un poco.
Las anotaciones estructurales son simplemente xml aleatorio agregado al archivo EDMX. El archivo EDMX es, de hecho, solo XML, que tiene 4 partes: CSDL, MSL, SSDL y parte relacionada con elementos de posicionamiento en el diseñador.
- CSDL describe entidades y asociaciones entre entidades (definidos en el diseñador)
- SSDL describe las tablas y las relaciones
- MSL describe mapeo entre CSDL y SSDL
Si se inicia con el modelo de primera (desea generar la base de datos desde su modelo), solo tiene parte CSDL y ambos SSDL y MSL se generarán mediante un proceso automático (plantillas T4 ejecutadas en flujo de trabajo) una vez que se cree SSDL otra plantilla T4 generará una secuencia de comandos SQL para la creación de la base de datos.
La anotación estructural descrita en el hilo del foro de MSDN vinculado es una pista. Deberá colocar la anotación estructural en la parte CSDL de EDMX (debe abrir EDMX como XML - hacer clic en el archivo en el explorador de soluciones y elegir Abrir con). Mi prueba CSDL describe entidad Usuario individual con tres propiedades (entidad es visible en pantalla más adelante en la respuesta):
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm"
xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration"
xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation"
xmlns:custom="http://tempuri.org/custom"
Namespace="Model" Alias="Self" >
<EntityContainer Name="ModelContainer" annotation:LazyLoadingEnabled="true">
<EntitySet Name="UsersSet" EntityType="Model.User" />
</EntityContainer>
<EntityType Name="User">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Type="Int32" Name="Id" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
<Property Type="String" Name="Login" Nullable="false" />
<Property Type="DateTime" Name="CreatedAt" Nullable="false">
<custom:SqlType edmx:CopyToSSDL="true">Date</custom:SqlType>
</Property>
</EntityType>
</Schema>
</edmx:ConceptualModels>
he añadido definición de espacio de nombres personalizado en Schema
elemento: xmlns:custom="http://tempuri.org/custom"
y definidos anotación personalizada estructural para CreatedAt
propiedad:
<Property Type="DateTime" Name="CreatedAt" Nullable="false">
<custom:SqlType edmx:CopyToSSDL="true">Date</custom:SqlType>
</Property>
El nombre del espacio de nombre o elemento utilizado para la anotación estructural no es importante; depende de usted el nombre que use. Lo único importante es el atributo edmx:CopyToSSDL="true"
. Este atributo es reconocido por la plantilla T4 utilizada para la creación de SSDL y solo toma este elemento y lo coloca en SSDL. Generada SSDL parece:
<Schema Namespace="Model.Store" Alias="Self"
Provider="System.Data.SqlClient" ProviderManifestToken="2008"
xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
<EntityContainer Name="ModelStoreContainer">
<EntitySet Name="UsersSet" EntityType="Model.Store.UsersSet" store:Type="Tables" Schema="dbo" />
</EntityContainer>
<EntityType Name="UsersSet">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="int" StoreGeneratedPattern="Identity" Nullable="false" />
<Property Name="Login" Type="nvarchar(max)" Nullable="false" />
<Property Name="CreatedAt" Type="datetime" Nullable="false">
<custom:SqlType xmlns:custom="http://tempuri.org/custom">Date</custom:SqlType>
</Property>
</EntityType>
</Schema>
El único punto estaba moviendo la anotación estructural para SSDL. Se puede acceder a todas las anotaciones en metadatos a través de una colección de valores de nombre. Ahora necesita modificar la plantilla T4 responsable de la generación de scripts SQL para reconocer esta anotación y usar el valor definido en la anotación en lugar del tipo definido en la propiedad.Puede encontrar la plantilla en:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt
archivo de plantilla de copia a la nueva ubicación (para que no se modifique la original) y reemplazar creación de la tabla por defecto con esto:
-- Creating table '<#=tableName#>'
CREATE TABLE <# if (!IsSQLCE) {#>[<#=schemaName#>].<#}#>[<#=tableName#>] (
<#
for (int p = 0; p < entitySet.ElementType.Properties.Count; p++)
{
EdmProperty prop = entitySet.ElementType.Properties[p];
#>
[<#=Id(prop.Name)#>] <#
if (prop.MetadataProperties.Contains("http://tempuri.org/custom:SqlType"))
{
MetadataProperty annotationProperty = prop.MetadataProperties["http://tempuri.org/custom:SqlType"];
XElement e = XElement.Parse(annotationProperty.Value.ToString());
string value = e.Value.Trim();
#>
<#=value#> <# } else { #> <#=prop.ToStoreType()#> <# } #> <#=WriteIdentity(prop, targetVersion)#> <#=WriteNullable(prop.Nullable)#><#=(p < entitySet.ElementType.Properties.Count - 1) ? "," : ""#>
<#
}
#>
);
GO
Ahora la última punto es cambiar la plantilla utilizada para la generación de scripts SQL. Abra el archivo EDMX en el diseñador y vaya a las propiedades del modelo (simplemente haga clic en algún lugar del diseñador mientras tiene la ventana de propiedades abierta). Cambie la Plantilla de generación de DDL a la plantilla que modificó.
Run Generar base de datos de modelo y se creará secuencia de comandos SQL que contiene:
-- Creating table 'UsersSet'
CREATE TABLE [dbo].[UsersSet] (
[Id] int IDENTITY(1,1) NOT NULL,
[Login] nvarchar(max) NOT NULL,
[CreatedAt] Date NOT NULL
);
GO
Esta es probablemente la característica más avanzada y oculta de EDMX he visto todavía. Las anotaciones junto con las plantillas T4 personalizadas le permiten tener un gran control sobre la generación de clases y SQL. Me imagino usar esto para definir, por ejemplo, índices de bases de datos o claves únicas al usar primero el modelo o agregar selectivamente algunos atributos personalizados a las clases de POCO generadas.
La razón por la que esto está tan oculto es porque no hay soporte de herramientas en VS listo para utilizar.
Guau, esa fue una explicación increíble. ¡Gracias! – Rillanon
Sí, esa plantilla TT es bastante desconocida, o simplemente, no se anuncia lo suficiente. Recientemente me encontré con esto cuando traté de resolver los problemas de la columna Commo n OptimisticLocking y TimeStamp, y una vez más cuando * realmente * quería tener DateTime + StoredGeneratedPatter = Identity para hacer que ma fuera GetDate predeterminado() en esa columna. Al ajustar la plantilla, fue tonto fácil. – quetzalcoatl
Si quisiera agregar el CopyToSSDL por defecto a través del código, es decir, C#, ¿hay algún atributo que pueda usar para lograr esto? – Donny