使用索引生成实体框架代码

发布于 2024-08-22 07:38:54 字数 50 浏览 4 评论 0原文

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

Is there a way to tell .NET 4 ADO.NET Entity's SQL Generator to create indexes for a specific column?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嘿哥们儿 2024-08-29 07:38:54

索引本身不受支持,但如果您前往 这篇文章您可以了解如何将此自定义功能添加到现有模板中。

在本文的示例中,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");

希望有所帮助!

Indices are not supported natively, but if you head to the "Influencing the DDL Generation" section of this article you can see how to add this custom functionality to an existing template.

In the article's example, the new index in your EDMX's CSDL would look something like this:

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

But to get this working you would have to modify a few things (see the link I provided for the details). Firstly, you'd have to declare that "myExtensions" namespace on the schema node:

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

Secondly, you'd have to modify the template found at:

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

The solution requires Linq, so add this to the top of the template:

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

And then add this to the bottom:

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

Most of that could be pretty easily modified to fit your needs. The article goes into more of the details, but the most important line in the above code is the one which fetches that custom "Index" extension node:

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

Hope that helps!

旧故 2024-08-29 07:38:54

补充 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 元素末尾添加自定义元素(不必将其放入 标记内):

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

     }   
   }
#>

Complementing Smudge's answer, there are some tricks that need to be done for this to work in EF 5.

For instance, edmx:CopyToSSDL="true" doesn't work right off the bat. You have to do some hacks:

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

And then in the custom property (notice the edmxv2):

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

See this link for more info.

Also, I did change some of the T4 code to make it more easy. I took this example as a working base to accomplish a more flexible custom elements syntax.

You could add a custom element at the end of the EntityType element for instance (you don't have to put it inside a <Property></Property> tag):

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

And then modify the .tt template:

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

     }   
   }
#>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文