Entity framework 首先添加实体框架代码索引(CTP5)

Entity framework 首先添加实体框架代码索引(CTP5),entity-framework,Entity Framework,有没有办法让EF CTP5在创建模式时创建索引 更新:请参阅EF 6.1如何处理此问题(如下所述)。您可以利用新CTP5的数据库类上的ExecuteSqlCommand方法,该方法允许对数据库执行原始SQL命令 为此调用SqlCommand方法的最佳位置是在已在自定义初始值设定项类中重写的种子方法内部。例如: protected override void Seed(EntityMappingContext context) { context.Database.ExecuteSqlCo

有没有办法让EF CTP5在创建模式时创建索引


更新:请参阅EF 6.1如何处理此问题(如下所述)。

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

为此调用SqlCommand方法的最佳位置是在已在自定义初始值设定项类中重写的种子方法内部。例如:

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

正如Mortezas答案的注释中提到的,如果使用迁移,则有一个CreateIndex/DropIndex方法

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

为了让它更简单一点,我写了一个非常简单的扩展方法,使它成为强类型的,作为我的灵感,我想与任何读过这个问题的人分享,也许也会喜欢这种方法。只需根据您的需要和命名索引的方式进行更改

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

公共静态void CreateUniqueIndex(此数据库,表达式)
{
if(数据库==null)
抛出新的ArgumentNullException(“数据库”);
//假定单数表名与模型类型的名称匹配
var tableName=typeof(TModel).Name;
var columnName=GetLambdaExpressionName(expression.Body);
var indexName=string.Format(“IX_{0}{1}”,tableName,columnName);
var createIndexSql=string.Format(“在{1}({2})上创建唯一索引{0})”,indexName,tableName,columnName;
ExecuteSqlCommand(createIndexSql);
}
公共静态字符串GetLambdaExpressionName(表达式)
{
MemberExpression memberExp=作为MemberExpression的表达式;
if(memberExp==null)
{
//检查它是否为非AryExpression并将其展开
var unaryExp=表达式为UnaryExpression;
如果(unaryExp!=null)
memberExp=unaryExp.Operator作为MemberExpression;
}
if(memberExp==null)
抛出新ArgumentException(“无法从表达式中获取名称”,“表达式”);
返回memberExp.Member.Name;
}

更新:从版本6.1及以后,有一个[Index]属性可用


有关更多信息,请参见

该功能不久将通过数据注释和Fluent API提供。Microsoft已将其添加到其公共待办事项列表中:


在此之前,您需要在自定义初始值设定项类上使用seed方法来执行SQL以创建唯一索引,如果您使用的是代码优先迁移,请创建新的迁移以添加唯一索引,然后使用
Up
Down
迁移方法中的
CreateIndex
DropIndex
方法来创建和删除索引。

在这里检查我的答案这允许您使用属性定义多列索引。

多么好的主意!我想除了这个,没有其他的内置支持了吧?不幸的是没有。我自己使用这个方法在这里创建了一个唯一的约束:对于Magic Unicorn edition(EF 4.1代码优先)——使用context.Database.ExecuteSqlCommand(“创建索引IX_NAME ON…”);如果您使用的是迁移,您希望这是基于代码的迁移的一部分,而不是种子方法,因为您可能会随着时间的推移添加索引。@ChrisMoschini:如果您在迁移中这样做,似乎有一个名为
CreateIndex
——我们不需要编写任何原始SQL的函数。您可以在此处投票支持此功能:@vasek7:MS回答并说您应该在此处投票:(我添加了我的+3)请参见此处的解决方案:在发布多个问题的复制粘贴样板/逐字回答时要小心,这些往往被社区标记为“垃圾邮件”。如果你这样做,那么通常意味着问题是重复的,因此将其标记为重复的:问题并不完全相同,因为它们使用不同版本的EF,现在我只使用EF5测试了我的解决方案,但它可以在这两个方面都起作用。。无论如何,我会编辑我的文章并参考其他文章…不错,尽管你不能创建多栏索引。在哪里添加这个索引?我在seed方法中尝试了它,但出现错误:找不到对象“”,因为它不存在或您没有permissions@majkinetor您可以在6.1中创建多列索引。它位于最后一个链接的msdn页面上。只需将index属性放在每个属性上,如下所示:
[index(“IX_BlogIdAndRating”/*对所有属性使用相同的名称*/,2/*更改每个属性的编号*/)]
    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;
    }