sql >> Database teknologi >  >> RDS >> Sqlserver

Hvordan bruger jeg strukturelle annoteringer til at indstille SQL-type til Dato i model first-tilgang

Strukturel anmærkning - flot. Det er første gang, jeg har hørt om denne funktion, men den virker. Jeg har lige prøvet det. Jeg vil prøve at forklare det lidt.

Strukturelle annotationer er blot tilfældige xml tilføjet til EDMX-fil. EDMX-fil er faktisk kun XML, som har 4 dele - CSDL, MSL, SSDL og en del relateret til positioneringselementer i designeren.

  • CSDL beskriver enheder og associationer mellem enheder (defineret i designeren)
  • SSDL beskriver tabeller og relationer
  • MSL beskriver kortlægning mellem CSDL og SSDL

Hvis du starter med model først (du vil generere database fra din model), har du kun CSDL-del, og både SSDL og MSL vil blive genereret af en eller anden automatisk proces (T4-skabeloner eksekveret i workflow), når SSDL er oprettet, vil en anden T4-skabelon generere SQL-script til databaseoprettelse.

Strukturel annotation beskrevet i linket MSDN-forums tråd er et tip. Du vil placere strukturelle annoteringer i CSDL-delen af ​​EDMX'en (du skal åbne EDMX som XML - klik på filen i Solution Explorer og vælg Åbn med). Min test-CSDL beskriver en enkelt brugerentitet med tre egenskaber (enheden er synlig på skærmbilledet senere i svaret):

<!-- 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>

Jeg har tilføjet en brugerdefineret navnerumsdefinition i Schema element:xmlns:custom="http://tempuri.org/custom" og defineret tilpasset strukturel annotation for CreatedAt ejendom:

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

Navnet på det navneområde eller element, der bruges til strukturel annotering, er ikke vigtigt - det er helt op til dig, hvilke navne du bruger. Det eneste vigtige er edmx:CopyToSSDL="true" attribut. Denne attribut genkendes af T4-skabelonen, der bruges til SSDL-oprettelse, og den tager bare dette element og placerer det i SSDL. Genereret SSDL ser sådan ud:

<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>

Det eneste punkt var at flytte den strukturelle annotation til SSDL. Alle annoteringer er tilgængelige i metadata gennem en eller anden navneværdiindsamling. Nu skal du ændre T4-skabelonen, der er ansvarlig for SQL-scriptgenerering, for at genkende denne annotation og bruge værdien defineret i annotationen i stedet for typen defineret i egenskaben. Du kan finde skabelonen i:

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt

Kopier skabelonfilen til en ny placering (så du ikke ændrer den originale) og erstat oprettelse af standardtabel med denne:

-- 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

Nu er det sidste punkt at ændre skabelonen, der bruges til SQL-scriptgenerering. Åbn EDMX-filen i designeren og gå til modellens egenskaber (klik blot et sted i designeren, mens du har vinduet Egenskaber åbent). Skift DDL Generation Template til den skabelon, du har ændret.

Kør Generer database fra model og det vil oprette SQL-script, der indeholder:

-- Creating table 'UsersSet'
CREATE TABLE [dbo].[UsersSet] (
    [Id]  int  IDENTITY(1,1) NOT NULL,
    [Login]  nvarchar(max)   NOT NULL,
    [CreatedAt]     Date   NOT NULL
);
GO

Dette er nok den mest avancerede og skjulte funktion af EDMX, jeg har set endnu. Annoteringer sammen med brugerdefinerede T4-skabeloner kan give dig meget kontrol over både klasse- og SQL-generering. Jeg kan forestille mig at bruge dette til at definere f.eks. databaseindekser eller unikke nøgler, når du bruger modellen først eller tilføje selektivt nogle brugerdefinerede attributter til genererede POCO-klasser.

Grunden til, at dette er så skjult, er, at der ikke er nogen værktøjsunderstøttelse i VS klar til at bruge dette.



  1. Parse mySQL-forespørgselsresultater og form array for if/else

  2. JavaScript (Postgres DB) - Sådan bruges en forberedt sætning med et array som parameter i WHERE IN ( )-sætningen

  3. pgAdmin - Deling af DB-forbindelsesdefinitioner

  4. Vis alle datoer mellem, selvom der ikke er noget resultat