Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie verwende ich strukturelle Anmerkungen, um den SQL-Typ im ersten Ansatz des Modells auf Date festzulegen?

Strukturelle Anmerkung - nett. Es ist das erste Mal, dass ich von dieser Funktion höre, aber es funktioniert. Ich habe es gerade versucht. Ich werde versuchen, es ein bisschen zu erklären.

Strukturelle Anmerkungen sind nur zufällige XML-Dateien, die der EDMX-Datei hinzugefügt werden. Die EDMX-Datei ist eigentlich nur XML, das aus 4 Teilen besteht – CSDL, MSL, SSDL und einem Teil, der sich auf die Positionierung von Elementen im Designer bezieht.

  • CSDL beschreibt Entitäten und Zuordnungen zwischen Entitäten (im Designer definiert)
  • SSDL beschreibt Tabellen und Relationen
  • MSL beschreibt die Zuordnung zwischen CSDL und SSDL

Wenn Sie zuerst mit dem Modell beginnen (Sie möchten eine Datenbank aus Ihrem Modell generieren), haben Sie nur den CSDL-Teil und sowohl SSDL als auch MSL werden durch einen automatischen Prozess generiert (T4-Vorlagen werden im Workflow ausgeführt), sobald SSDL erstellt ist, wird eine weitere T4-Vorlage generiert SQL-Skript zur Datenbankerstellung.

Die im Thread des verlinkten MSDN-Forums beschriebene strukturelle Anmerkung ist ein Hinweis. Sie platzieren strukturelle Anmerkungen im CSDL-Teil des EDMX (Sie müssen EDMX als XML öffnen – klicken Sie im Projektmappen-Explorer auf die Datei und wählen Sie „Öffnen mit“). Meine Test-CSDL beschreibt eine einzelne Benutzerentität mit drei Eigenschaften (die Entität ist auf dem Screenshot später in der Antwort sichtbar):

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

Ich habe eine benutzerdefinierte Namespace-Definition in Schema hinzugefügt Element:xmlns:custom="http://tempuri.org/custom" und definierte benutzerdefinierte strukturelle Anmerkungen für CreatedAt Eigenschaft:

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

Der Name des Namensraums oder des Elements, das für die strukturelle Annotation verwendet wird, ist nicht wichtig – es liegt ganz bei Ihnen, welche Namen Sie verwenden. Wichtig ist nur edmx:CopyToSSDL="true" Attribut. Dieses Attribut wird von der T4-Vorlage erkannt, die für die SSDL-Erstellung verwendet wird, und es nimmt einfach dieses Element und platziert es in SSDL. Generierte SSDL sieht so aus:

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

Der einzige Punkt war das Verschieben der strukturellen Anmerkung zu SSDL. Auf alle Anmerkungen kann in Metadaten über eine Sammlung von Namenswerten zugegriffen werden. Jetzt müssen Sie die für die SQL-Skriptgenerierung verantwortliche T4-Vorlage ändern, um diese Anmerkung zu erkennen und den in der Anmerkung definierten Wert anstelle des in der Eigenschaft definierten Typs zu verwenden. Sie finden die Vorlage in:

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

Kopieren Sie die Vorlagendatei an einen neuen Speicherort (damit Sie die ursprüngliche nicht ändern) und ersetzen Sie die Standardtabellenerstellung durch diese:

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

Der letzte Punkt ist jetzt das Ändern der Vorlage, die für die SQL-Skriptgenerierung verwendet wird. Öffnen Sie die EDMX-Datei im Designer und gehen Sie zu den Eigenschaften des Modells (klicken Sie einfach irgendwo im Designer, während Sie das Eigenschaftsfenster geöffnet haben). Ändern Sie die DDL-Generierungsvorlage in die von Ihnen geänderte Vorlage.

Führen Sie Datenbank aus Modell generieren aus und es wird ein SQL-Skript erstellt, das Folgendes enthält:

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

Dies ist wahrscheinlich die fortschrittlichste und versteckteste Funktion von EDMX, die ich bisher gesehen habe. Anmerkungen zusammen mit benutzerdefinierten T4-Vorlagen können Ihnen viel Kontrolle über die Klassen- und SQL-Generierung verschaffen. Ich kann mir vorstellen, dies zu verwenden, um beispielsweise Datenbankindizes oder eindeutige Schlüssel zu definieren, wenn zuerst das Modell verwendet wird, oder um selektiv einige benutzerdefinierte Attribute zu generierten POCO-Klassen hinzuzufügen.

Der Grund, warum dies so versteckt ist, ist, dass es in VS keine standardmäßige Werkzeugunterstützung gibt, um dies zu verwenden.