如何使用结构注释在模型第一种方法中将SQL类型设置为Date

时间:2011-05-06 14:26:23

标签: sql entity-framework sql-server-2008 entity-framework-4 entity

是否可以通过实体框架设计器将类型设置为日期(非日期时间)?

我环顾四周,我发现的唯一答案是一年前来自MSDN论坛的帖子......

http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/28e45675-f64b-41f0-9f36-03b67cdf2e1b

我在这里很新,我不太明白他们谈论结构注释的说明......

我可以浏览生成的SQL脚本并更改每一行,但我宁愿不这样做......

2 个答案:

答案 0 :(得分:18)

结构注释 - 很好。这是我第一次听说这个功能,但它确实有效。我刚尝试过。我会尝试解释一下。

结构注释只是随机xml添加到EDMX文件中。 EDMX文件实际上只是XML,它有4个部分--CSDL,MSL,SSDL和与设计器中定位元素相关的部分。

  • CSDL描述实体之间的实体和关联(在设计者中定义)
  • SSDL描述表和关系
  • MSL描述了CSDL和SSDL之间的映射

如果你首先从模型开始(你想从你的模型生成数据库),你只有CSDL部分,一旦自己创建了SSDL,一些自动过程(在工作流中执行的T4模板)生成了SSDL和MSL模板将生成用于创建数据库的SQL脚本。

在链接的MSDN论坛的主题中描述的结构注释是一个提示。您将结构注释放入EDMX的CSDL部分(您必须以XML格式打开EDMX - 单击解决方案资源管理器中的文件并选择打开方式)。我的测试CSDL描述了具有三个属性的单个用户实体(实体在答案后面的屏幕截图中可见):

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

我在Schema元素中添加了自定义命名空间定义:xmlns:custom="http://tempuri.org/custom"并为CreatedAt属性定义了自定义结构注释:

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

用于结构注释的命名空间或元素的名称并不重要 - 它完全取决于您使用的名称。唯一重要的是edmx:CopyToSSDL="true"属性。此属性由用于SSDL创建的T4模板识别,它只接受此元素并将其放置到SSDL。生成的SSDL看起来像:

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

唯一的一点是将结构注释移动到SSDL。可以通过某些名称值集合在元数据中访问所有注释。现在,您需要修改负责SQL脚本生成的T4模板以识别此批注,并使用批注中定义的值而不是属性中定义的类型。您可以在以下位置找到该模板:

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

将模板文件复制到新位置(这样就不会修改原始文件)并将默认表创建替换为:

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

现在最后一点是更改用于生成SQL脚本的模板。在设计器中打开EDMX文件并转到模型的属性(只需在打开属性窗口时单击设计器中的某个位置)。将DDL生成模板更改为您修改的模板。

enter image description here

运行从模型生成数据库,它将创建包含以下内容的SQL脚本:

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

这可能是我见过的EDMX最先进和隐藏的功能。注释与自定义T4模板一起可以让您对类和SQL生成进行大量控制。我可以想象使用它来定义例如首先使用模型时的数据库索引或唯一键,或者选择性地将一些自定义属性添加到生成的POCO类中。

之所以如此隐藏的原因是VS开箱即用的工具支持不能使用它。

答案 1 :(得分:0)

从NuGet寻找TiraggoEdmx,它以非常好的方式提供EDMX文件中的所有低级信息。见http://brewdawg.github.io/Tiraggo.Edmx/