【问题标题】:Add index with entity framework code first (CTP5)先用实体框架代码添加索引(CTP5)
【发布时间】:2011-06-27 02:36:22
【问题描述】:

有没有办法让 EF CTP5 在创建架构时创建索引?

更新:请参阅 here 了解 EF 6.1 如何处理此问题(如下面的 juFo 所指出的)。

【问题讨论】:

标签: entity-framework


【解决方案1】:

正如一些人在对 Mortezas 的回答中提到的那样,如果您使用迁移,则有一个 CreateIndex/DropIndex 方法。

但是,如果您处于“调试”/开发模式并且一直在更改架构并且每次都在重新创建数据库,那么您可以使用 Morteza 回答中提到的示例。

为了让它更简单一点,我编写了一个非常简单的扩展方法来使其成为强类型,作为我想与阅读这个问题并且可能也喜欢这种方法的任何人分享的灵感。只需更改它以适合您的需求和命名索引的方式。

You use it like this: context.Database.CreateUniqueIndex<User>(x => x.Name);

.

    public static void CreateUniqueIndex<TModel>(this Database database, Expression<Func<TModel, object>> expression)
    {
        if (database == null)
            throw new ArgumentNullException("database");

        // Assumes singular table name matching the name of the Model type

        var tableName = typeof(TModel).Name;
        var columnName = GetLambdaExpressionName(expression.Body);
        var indexName = string.Format("IX_{0}_{1}", tableName, columnName);

        var createIndexSql = string.Format("CREATE UNIQUE INDEX {0} ON {1} ({2})", indexName, tableName, columnName);

        database.ExecuteSqlCommand(createIndexSql);
    }

    public static string GetLambdaExpressionName(Expression expression)
    {
        MemberExpression memberExp = expression as MemberExpression;

        if (memberExp == null)
        {
            // Check if it is an UnaryExpression and unwrap it
            var unaryExp = expression as UnaryExpression;
            if (unaryExp != null)
                memberExp = unaryExp.Operand as MemberExpression;
        }

        if (memberExp == null)
            throw new ArgumentException("Cannot get name from expression", "expression");

        return memberExp.Member.Name;
    }

更新:从 6.1 版起,有一个 [Index] 属性可用。

欲了解更多信息,请参阅http://msdn.microsoft.com/en-US/data/jj591583#Index

【讨论】:

  • 很好,虽然你不能创建多列索引。
  • 在哪里添加这个索引?我在种子方法中尝试过,但出现错误:找不到对象“”,因为它不存在或您没有权限
  • @majkinetor 你可以在 6.1 中创建多列索引。它位于最后一个链接的 msdn 页面上。只需将 index 属性放在每个属性上,如下所示:[Index("IX_BlogIdAndRating" /*use the same name for all properties*/, 2 /*change the number for each property*/)]
【解决方案2】:

在这里查看我的答案Entity Framework Code First Fluent Api: Adding Indexes to columns 这允许您通过使用属性上的属性来定义多列索引。

【讨论】:

  • 在发布多个问题的复制和粘贴样板/逐字答案时要小心,这些往往会被社区标记为“垃圾邮件”。如果您这样做,则通常意味着问题是重复的,因此请将它们标记为:stackoverflow.com/a/13144786/419
  • 好吧,这些问题并不相同,因为它们使用不同版本的 EF,现在我只用 EF5 测试了我的解决方案,但它可以在这两种情况下工作.. 无论如何编辑我的帖子并参考另一个发布...
【解决方案3】:

该功能应该在不久的将来通过数据注释和 Fluent API 提供。微软已将其添加到他们的公开积压中:

http://entityframework.codeplex.com/workitem/list/basic?keywords=DevDiv [Id=87553]

在此之前,您需要在自定义 Initializer 类上使用种子方法来执行 SQL 以创建唯一索引,如果您使用的是代码优先迁移,请创建一个新迁移以添加唯一索引,并使用 UpDown 迁移方法中的 CreateIndexDropIndex 方法来创建和删除索引。

【讨论】:

    【解决方案4】:

    您可以利用 Database 类上的新 CTP5 的 ExecuteSqlCommand 方法,该方法允许对数据库执行原始 SQL 命令。

    为此目的调用 SqlCommand 方法的最佳位置是在自定义 Initializer 类中已被覆盖的 Seed 方法内。例如:

    protected override void Seed(EntityMappingContext context)
    {
        context.Database.ExecuteSqlCommand("CREATE INDEX IX_NAME ON ...");
    }
    

    【讨论】:

    • 好主意!我认为除此之外没有内置支持?
    • 很遗憾没有。我自己在这里使用这种方法创建了一个唯一的约束:weblogs.asp.net/manavi/archive/2011/01/23/…
    • 对于 Magic Unicorn 版本(EF 4.1 Code-First)——使用 context.Database.ExecuteSqlCommand("CREATE INDEX IX_NAME ON ...");
    • 如果您使用迁移,您希望它成为基于代码的迁移的一部分,而不是您的种子方法,因为您可能会随着时间的推移添加索引。
    • @ChrisMoschini:如果您在迁移中执行此操作,似乎有一个名为 CreateIndex 的函数——我们不需要编写任何原始 SQL。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多