Strukturell anteckning - trevligt. Det är första gången jag hörde talas om den här funktionen men den fungerar. Jag har precis provat det. Jag ska försöka förklara det lite.
Strukturella kommentarer är bara slumpmässiga xml som läggs till EDMX-filen. EDMX-filen är i själva verket bara XML som har 4 delar - CSDL, MSL, SSDL och en del relaterad till positioneringselement i designern.
- CSDL beskriver enheter och associationer mellan enheter (definierad i designern)
- SSDL beskriver tabeller och relationer
- MSL beskriver mappning mellan CSDL och SSDL
Om du börjar med modellen först (du vill generera databas från din modell), har du bara CSDL-del och både SSDL och MSL kommer att genereras av någon automatisk process (T4-mallar exekveras i arbetsflödet) när SSDL har skapats kommer en annan T4-mall att generera SQL-skript för att skapa databas.
Strukturell anteckning som beskrivs i länkade MSDN-forums tråd är ett tips. Du kommer att placera strukturella anteckningar i CSDL-delen av EDMX (du måste öppna EDMX som XML - klicka på filen i lösningsutforskaren och välj Öppna med). Min test-CSDL beskriver en enda användarenhet med tre egenskaper (entiteten är synlig på skärmdumpen längre fram 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>
Jag har lagt till anpassad namnområdesdefinition i Schema
element:xmlns:custom="http://tempuri.org/custom"
och definierade anpassade strukturella kommentarer för CreatedAt
egenskap:
<Property Type="DateTime" Name="CreatedAt" Nullable="false">
<custom:SqlType edmx:CopyToSSDL="true">Date</custom:SqlType>
</Property>
Namnet på namnutrymmet eller elementet som används för strukturell anteckning är inte viktigt - det är helt upp till dig vilka namn du använder. Det enda viktiga är edmx:CopyToSSDL="true"
attribut. Det här attributet känns igen av T4-mall som används för att skapa SSDL och det tar bara detta element och placerar det i SSDL. Genererad SSDL ser ut så här:
<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>
Den enda punkten var att flytta den strukturella anteckningen till SSDL. Alla kommentarer är tillgängliga i metadata genom någon namnvärdessamling. Nu måste du ändra T4-mall som är ansvarig för SQL-skriptgenerering för att känna igen denna anteckning och använda värdet som definierats i anteckningen istället för typen som definieras i egenskapen. Du hittar mallen i:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt
Kopiera mallfilen till en ny plats (så att du inte ändrar den ursprungliga) och ersätt skapande av standardtabeller med detta:
-- 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 är den sista punkten att ändra mallen som används för generering av SQL-skript. Öppna EDMX-filen i designern och gå till modellens egenskaper (klicka bara någonstans i designern medan du har egenskapsfönstret öppet). Ändra DDL Generation Mall till mallen du ändrade.
Kör Generera databas från modell och det kommer att skapa SQL-skript som innehåller:
-- Creating table 'UsersSet'
CREATE TABLE [dbo].[UsersSet] (
[Id] int IDENTITY(1,1) NOT NULL,
[Login] nvarchar(max) NOT NULL,
[CreatedAt] Date NOT NULL
);
GO
Detta är förmodligen den mest avancerade och dolda funktionen hos EDMX jag har sett hittills. Anteckningar tillsammans med anpassade T4-mallar kan ge dig mycket kontroll över både klass- och SQL-generering. Jag kan tänka mig att använda detta för att definiera till exempel databasindex eller unika nycklar när man använder modellen först eller lägga till selektivt några anpassade attribut till genererade POCO-klasser.
Anledningen till att detta är så dolt är att det inte finns något verktygsstöd i VS direkt för att använda detta.