sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cómo uso las anotaciones estructurales para establecer el tipo de SQL en Fecha en el primer enfoque del modelo?

Anotación estructural - agradable. Es la primera vez que oigo hablar de esta función, pero funciona. Lo acabo de probar. Intentaré explicarlo un poco.

Las anotaciones estructurales son solo xml aleatorios agregados al archivo EDMX. El archivo EDMX es, de hecho, solo XML que tiene 4 partes:CSDL, MSL, SSDL y una parte relacionada con los elementos de posicionamiento en el diseñador.

  • CSDL describe entidades y asociaciones entre entidades (definidas en el diseñador)
  • SSDL describe tablas y relaciones
  • MSL describe el mapeo entre CSDL y SSDL

Si comienza con el modelo primero (quiere generar una base de datos a partir de su modelo), solo tiene una parte CSDL y tanto SSDL como MSL se generarán mediante algún proceso automático (las plantillas T4 se ejecutan en el flujo de trabajo) una vez que se crea SSDL, se generará otra plantilla T4 Script SQL para la creación de bases de datos.

La anotación estructural descrita en el hilo del foro de MSDN vinculado es una pista. Colocará la anotación estructural en la parte CSDL del EDMX (debe abrir EDMX como XML; haga clic en el archivo en el explorador de soluciones y elija Abrir con). Mi CSDL de prueba describe una sola entidad de Usuario con tres propiedades (la entidad es visible en la captura de 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 agregado una definición de espacio de nombres personalizado en Schema elemento:xmlns:custom="http://tempuri.org/custom" y definió una anotación estructural personalizada para CreatedAt propiedad:

<Property Type="DateTime" Name="CreatedAt" Nullable="false">
   <custom:SqlType edmx:CopyToSSDL="true">Date</custom:SqlType>
</Property>

El nombre del espacio de nombres o el elemento utilizado para la anotación estructural no es importante; depende absolutamente de usted qué nombres usa. Lo único importante es edmx:CopyToSSDL="true" atributo. Este atributo es reconocido por la plantilla T4 utilizada para la creación de SSDL y simplemente toma este elemento y lo coloca en SSDL. SSDL generado se parece a:

<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 fue mover la anotación estructural a SSDL. Se puede acceder a todas las anotaciones en los metadatos a través de alguna colección de valores de nombre. Ahora necesita modificar la plantilla T4 responsable de la generación de secuencias de comandos 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

Copie el archivo de plantilla en la nueva ubicación (para que no modifique el original) y reemplace la creación de la tabla predeterminada 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, el último punto es cambiar la plantilla utilizada para la generación de secuencias de comandos 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 abierta la ventana de propiedades). Cambie la plantilla de generación de DDL a la plantilla que modificó.

Ejecute Generar base de datos a partir del modelo y creará un script SQL que contenga:

-- 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 que he visto hasta ahora. Las anotaciones junto con las plantillas T4 personalizadas pueden brindarle mucho control sobre la generación de clases y SQL. Puedo imaginar usar esto para definir, por ejemplo, índices de base de datos o claves únicas al usar el modelo primero o agregar selectivamente algunos atributos personalizados a las clases POCO generadas.

La razón por la que esto está tan oculto es que no hay soporte de herramientas en VS listo para usar para usar esto.