sql >> Database >  >> RDS >> Sqlserver

Hoe gebruik ik structurele annotaties om het SQL-type in te stellen op Datum in de eerste benadering van het model?

Structurele annotatie - leuk. Het is de eerste keer dat ik over deze functie hoor, maar het werkt. Ik heb het net geprobeerd. Ik zal proberen het een beetje uit te leggen.

Structurele annotaties zijn gewoon willekeurige xml toegevoegd aan het EDMX-bestand. EDMX-bestand is in feite gewoon XML met 4 delen - CSDL, MSL, SSDL en een deel gerelateerd aan positioneringselementen in de ontwerper.

  • CSDL beschrijft entiteiten en associaties tussen entiteiten (gedefinieerd in de ontwerper)
  • SSDL beschrijft tabellen en relaties
  • MSL beschrijft mapping tussen CSDL en SSDL

Als u eerst met het model begint (u wilt een database van uw model genereren), heeft u alleen een CSDL-gedeelte en zowel SSDL als MSL worden gegenereerd door een of ander automatisch proces (T4-sjablonen uitgevoerd in workflow) zodra SSDL is gemaakt, zal een andere T4-sjabloon genereren SQL-script voor het maken van databases.

Structurele annotatie beschreven in de thread van het gekoppelde MSDN-forum is een hint. U plaatst structurele annotaties in het CSDL-gedeelte van de EDMX (u moet EDMX openen als XML - klik op het bestand in de oplossingsverkenner en kies Openen met). Mijn test-CSDL beschrijft een enkele gebruikersentiteit met drie eigenschappen (entiteit is zichtbaar op screenshot verderop in het antwoord):

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

Ik heb een aangepaste naamruimtedefinitie toegevoegd in Schema element:xmlns:custom="http://tempuri.org/custom" en gedefinieerde aangepaste structurele annotatie voor CreatedAt eigendom:

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

De naam van de naamruimte of het element dat wordt gebruikt voor structurele annotatie is niet belangrijk - het is geheel aan jou welke namen je gebruikt. Het enige belangrijke is edmx:CopyToSSDL="true" attribuut. Dit attribuut wordt herkend door de T4-sjabloon die wordt gebruikt voor het maken van SSDL's en het neemt dit element en plaatst het naar SSDL. Gegenereerde SSDL ziet eruit als:

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

Het enige punt was het verplaatsen van de structurele annotatie naar SSDL. Alle annotaties zijn toegankelijk in metadata via een verzameling van naamwaarden. Nu moet u de T4-sjabloon die verantwoordelijk is voor het genereren van SQL-scripts wijzigen om deze annotatie te herkennen en de waarde te gebruiken die in de annotatie is gedefinieerd in plaats van het type dat in de eigenschap is gedefinieerd. U vindt de sjabloon in:

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

Kopieer het sjabloonbestand naar een nieuwe locatie (zodat u de originele niet wijzigt) en vervang de standaardtabelcreatie hiermee:

-- 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 is het laatste punt het wijzigen van de sjabloon die wordt gebruikt voor het genereren van SQL-scripts. Open het EDMX-bestand in de ontwerper en ga naar de eigenschappen van het model (klik gewoon ergens in de ontwerper terwijl u het eigenschappenvenster hebt geopend). Wijzig de sjabloon voor DDL-generatie in de sjabloon die u hebt gewijzigd.

Voer Database genereren uit model uit en het zal een SQL-script maken met daarin:

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

Dit is waarschijnlijk de meest geavanceerde en verborgen functie van EDMX die ik tot nu toe heb gezien. Annotaties samen met aangepaste T4-sjablonen kunnen u veel controle geven over zowel klasse- als SQL-generatie. Ik kan me voorstellen dat ik dit gebruik om bijvoorbeeld database-indexen of unieke sleutels te definiëren wanneer ik eerst het model gebruik of selectief enkele aangepaste attributen toe te voegen aan gegenereerde POCO-klassen.

De reden waarom dit zo verborgen is, is dat er in VS geen kant-en-klare tooling-ondersteuning is om dit te gebruiken.



  1. Hoe substrings wijzigen?

  2. Hoe ontvang ik automatische meldingen over wijzigingen in tabellen?

  3. Meerdere relaties tussen twee entiteiten, is dit een goede gewoonte?

  4. Som van minuten tussen meerdere perioden