Создание кода Entity Framework с помощью индексов - PullRequest
1 голос
/ 21 февраля 2010

Есть ли способ указать .NET 4 ADO.NET Entity SQL Generator для создания индексов для определенного столбца?

Ответы [ 2 ]

1 голос
/ 01 декабря 2011

Индексы изначально не поддерживаются, но если вы перейдете к разделу «Влияние на генерацию DDL» в этой статье , вы сможете увидеть, как добавить эти пользовательские функции в существующий шаблон.

В примере статьи новый индекс в CSDL вашего EDMX будет выглядеть примерно так:

<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 \ 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 голосов
/ 23 октября 2013

В дополнение к ответу 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" >

См. эту ссылку для получения дополнительной информации.

Кроме того, я немного изменил код T4, чтобы сделать его более простым. Я взял этот пример в качестве рабочей базы для создания более гибкого синтаксиса пользовательских элементов.

Вы можете добавить пользовательский элемент в конце элемента 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#>]);
<#

     }   
   }
#>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...