【问题标题】:Entity Framework Code Generation with Indexes使用索引生成实体框架代码
【发布时间】:2010-02-21 11:46:07
【问题描述】:

有没有办法告诉 .NET 4 ADO.NET 实体的 SQL 生成器为特定列创建索引?

【问题讨论】:

  • @Andomar。抱歉,我认为您的评论在目前的形式中没有特别的帮助。也许你可以解释一下,并为你的陈述和观点提供一些理由。还要记住,Jameszhao00 可能无法做出技术选择,但可能会被困在尝试使用实体框架在预先存在的系统中实现特定目标。虽然我不一定完全不同意你的观点,但我认为背景很重要。

标签: c# sql entity-framework ado.net indexing


【解决方案1】:

本机不支持索引,但如果您前往this 文章的“影响 DDL 生成”部分,您可以了解如何将此自定义功能添加到现有模板。

在本文的示例中,EDMX 的 CSDL 中的新索引如下所示:

<Property ... >
  <myExtensions:Index indexName="Seat" edmx:CopyToSSDL="true"/>
</Property>

但要使其正常工作,您必须修改一些内容(有关详细信息,请参阅我提供的链接)。首先,您必须在模式节点上声明“myExtensions”命名空间:

<!-- CSDL content -->
<edmx:ConceptualModels>
  <Schema [...] xmlns:myExtensions="http://www.microsoft.com/userExtensions">
  [...]
</edmx>

其次,您必须修改在以下位置找到的模板:

\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt

该解决方案需要 Linq,因此将其添加到模板顶部:

<#@ assembly name="System.Xml.Linq" #>

然后将这个添加到底部:

-- Creating index for table based on custom extensions --
<#
   foreach (EntitySet entitySet in Store.GetAllEntitySets())
   {
     string tableName = Id(entitySet.GetTableName());
     string schemaName = Id(entitySet.GetSchemaName());
     EdmProperties props = entitySet.ElementType.Properties;
     foreach (EdmProperty ep in props.Where(p =>
                           p.TypeUsage.EdmType is PrimitiveType))
     {
        MetadataProperty meta = ep.MetadataProperties.FirstOrDefault(mp => mp.Name == "http://www.microsoft.com/userExtensions:Index");
        if (meta != null)
        {
            System.Xml.Linq.XElement e = meta.Value as System.Xml.Linq.XElement;
            System.Xml.Linq.XAttribute attr = e.Attributes().FirstOrDefault(a => a.Name == "indexName");
            string indexName = attr.Value;     
            // create an index for specified column
#>
CREATE INDEX [IX_<#=indexName#>]
ON <#if (!IsSQLCE) {#>[<#=schemaName#>].<#}#>[<#=tableName#>]
([<#=indexName#>]);
<#
         }
     }   
   }
#>

其中大部分都可以很容易地修改以满足您的需求。本文详细介绍了更多细节,但上述代码中最重要的一行是获取自定义“索引”扩展节点的那一行:

MetadataProperty meta = ep.MetadataProperties.FirstOrDefault(mp => mp.Name == "http://www.microsoft.com/userExtensions:Index");

希望有帮助!

【讨论】:

    【解决方案2】:

    补充 Smudge 的回答,需要做一些技巧才能在 EF 5 中工作。

    例如,edmx:CopyToSSDL="true" 不能立即工作。你必须做一些技巧:

    <Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm" xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration"
                  xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" Namespace="CPEData" Alias="Self"
                  xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation" annotation:UseStrongSpatialTypes="false"
                  xmlns:myExtensions="http://www.microsoft.com/userExtensions"
                  xmlns:edmxv2="http://schemas.microsoft.com/ado/2008/10/edmx" >
    

    然后在自定义属性中(注意edmxv2):

    <myExtensions:Index edmxv2:CopyToSSDL="true" IndexName="Name" Columns="Name" >
    

    请参阅this link 了解更多信息。

    另外,我确实更改了一些 T4 代码以使其更容易。我以this example 为工作基础来完成更灵活的自定义元素语法。

    例如,您可以在 EntityType 元素的末尾添加一个自定义元素(您不必将其放在 &lt;Property&gt;&lt;/Property&gt; 标记中):

    <myExtensions:Index edmxv2:CopyToSSDL="true" IndexName="Name" Columns="Name" >
        Custom metadata (not needed)
    </myExtensions:Index>
    

    然后修改.tt模板:

    -- --------------------------------------------------
    -- Creating all Indexes based on custom extensions   
    -- --------------------------------------------------
    
    <#
       foreach (EntitySet entitySet in Store.GetAllEntitySets())
       {
         string tableName = Id(entitySet.GetTableName());
         string schemaName = Id(entitySet.GetSchemaName());
         var props = entitySet.ElementType.MetadataProperties.Where(p => p.Name == "http://www.microsoft.com/userExtensions:Index");
         foreach (MetadataProperty meta in props)
         {
            System.Xml.Linq.XElement e = meta.Value as System.Xml.Linq.XElement;
            string indexName = e.Attributes().FirstOrDefault(a => a.Name == "IndexName").Value;
            string columnsName = e.Attributes().FirstOrDefault(a => a.Name == "Columns").Value;
            // create an index for specified column
    #>
    CREATE INDEX [IX_<#=indexName#>]
    ON <#if (!IsSQLCE) {#>[<#=schemaName#>].<#}#>[<#=tableName#>]
    ([<#=columnsName#>]);
    <#
    
         }   
       }
    #>
    

    【讨论】:

      猜你喜欢
      • 2012-04-15
      • 1970-01-01
      • 2012-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-10
      • 2011-06-27
      • 1970-01-01
      相关资源
      最近更新 更多