Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como uso anotações estruturais para definir o tipo SQL como Data na primeira abordagem do modelo


Anotação estrutural - agradável. É a primeira vez que ouvi falar sobre esse recurso, mas funciona. Acabei de tentar. Vou tentar explicar um pouco.

As anotações estruturais são apenas xml aleatórios adicionados ao arquivo EDMX. O arquivo EDMX é na verdade apenas XML que possui 4 partes - CSDL, MSL, SSDL e parte relacionada aos elementos de posicionamento no designer.
  • CSDL descreve entidades e associações entre entidades (definidas no designer)
  • O SSDL descreve tabelas e relações
  • MSL descreve o mapeamento entre CSDL e SSDL

Se você começar com o modelo primeiro (você deseja gerar o banco de dados do seu modelo), você tem apenas a parte CSDL e tanto o SSDL quanto o MSL serão gerados por algum processo automático (modelos T4 executados no fluxo de trabalho) assim que o SSDL for criado, outro modelo T4 será gerado Script SQL para criação de banco de dados.

A anotação estrutural descrita no tópico do fórum do MSDN vinculado é uma dica. Você colocará a anotação estrutural na parte CSDL do EDMX (você deve abrir o EDMX como XML - clique no arquivo no gerenciador de soluções e escolha Abrir com). Meu teste CSDL descreve uma entidade de usuário único com três propriedades (a entidade é visível na captura de tela posteriormente na resposta):
<!-- 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>

Eu adicionei uma definição de namespace personalizada em Schema elemento:xmlns:custom="http://tempuri.org/custom" e anotação estrutural personalizada definida para CreatedAt propriedade:
<Property Type="DateTime" Name="CreatedAt" Nullable="false">
   <custom:SqlType edmx:CopyToSSDL="true">Date</custom:SqlType>
</Property>

O nome do namespace ou elemento usado para anotação estrutural não é importante - depende absolutamente de você quais nomes você usa. A única coisa importante é edmx:CopyToSSDL="true" atributo. Esse atributo é reconhecido pelo modelo T4 usado para criação de SSDL e apenas pega esse elemento e o coloca em SSDL. O SSDL gerado se parece com:
<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>

O único ponto foi mover a anotação estrutural para SSDL. Todas as anotações são acessíveis nos metadados por meio de alguma coleção de valores de nome. Agora você precisa modificar o template T4 responsável pela geração do script SQL para reconhecer esta anotação e utilizar o valor definido na anotação ao invés do tipo definido na propriedade. Você pode encontrar o modelo em:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt

Copie o arquivo de modelo para o novo local (para que você não modifique o original) e substitua a criação da tabela padrão por este:
-- 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

Agora o último ponto é alterar o modelo usado para geração de script SQL. Abra o arquivo EDMX no designer e vá para as propriedades do modelo (basta clicar em algum lugar no designer enquanto a janela de propriedades está aberta). Altere o modelo de geração de DDL para o modelo que você modificou.



Execute Gerar banco de dados do modelo e ele criará um script SQL contendo:
-- Creating table 'UsersSet'
CREATE TABLE [dbo].[UsersSet] (
    [Id]  int  IDENTITY(1,1) NOT NULL,
    [Login]  nvarchar(max)   NOT NULL,
    [CreatedAt]     Date   NOT NULL
);
GO

Este é provavelmente o recurso mais avançado e oculto do EDMX que eu já vi. Anotações junto com modelos T4 personalizados podem lhe dar muito controle sobre a geração de classe e SQL. Posso imaginar usar isso para definir, por exemplo, índices de banco de dados ou chaves exclusivas ao usar o modelo primeiro ou adicionar seletivamente alguns atributos personalizados às classes POCO geradas.

A razão pela qual isso está tão oculto é que não há suporte de ferramentas no VS pronto para usar.