2010-02-21 78 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#>]); 
<# 

    } 
    } 
#> 
相關問題