2010-02-21 48 views
1

有没有办法告诉.NET 4 ADO.NET Entity的SQL Generator为特定列创建索引?带索引的实体框架代码生成

+8

@Andomar。对不起,我认为你的评论对目前的形式不是特别有用。也许你可以解释一下,为你的陈述和观点提供一些理由。请记住,Jameszhao00可能无法做出技术选择,但可能会停留在尝试使用实体框架来实现预先存在的系统中特定的某些内容。虽然我不一定完全不同意你的观点,但我认为背景很重要。 – 2010-02-21 13:46:33

回答

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> 

其次,你必须修改在发现模板:

\微软的Visual Studio 10.0 \ Common7 \ IDE \扩展\微软\实体框架工具\ 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"); 

希望帮助!

+0

非常好的答案,谢谢 – Francisco 2013-10-22 21:07:03

0

补充涂抹的答案,也有一些技巧,需要为这个做在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的末尾添加自定义元素(你不必把它放在<Property></Property>标签内):

<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#>]); 
<# 

    } 
    } 
#>