首页 > 解决方案 > 使用 EF Core 2.2 在 SQL 中为地理数据类型添加索引

问题描述

我首先使用 EF Core 2.2 代码来创建一个包含 NTS Point 属性的表。这工作正常,并在 SQL 中创建一个具有“地理”数据类型的表。现在我想先从代码中索引该列。我只是做一个基本的:

entity.HasIndex(x => x.Point);

我收到以下错误:

消息:System.Data.SqlClient.SqlException:表 'TableName' 中的列 'PointColumnName' 的类型对于用作索引或统计信息中的键列无效。

有没有办法先使用代码在此列上放置索引?

标签: c#.netentity-framework-core

解决方案


最简单的方法是根据需要自定义迁移脚本。例如:

migrationBuilder.Sql(
@"
    UPDATE Customer
    SET Name = FirstName + ' ' + LastName;
");

或者您可以使用更全面的方式自定义迁移操作

class MyMigrationsSqlGenerator : SqlServerMigrationsSqlGenerator
{
    public MyMigrationsSqlGenerator(
        MigrationsSqlGeneratorDependencies dependencies,
        IMigrationsAnnotationProvider migrationsAnnotations)
        : base(dependencies, migrationsAnnotations)
    {
    }

    protected override void Generate(
        MigrationOperation operation,
        IModel model,
        MigrationCommandListBuilder builder)
    {
        if (operation is CreateSpatialIndexOperation createSpatialIndexOperation)
        {
            Generate(createSpatialIndexOperation, builder);
        }
        else
        {
            base.Generate(operation, model, builder);
        }
    }

    private void Generate(
        CreateSpatialIndexOperation operation,
        MigrationCommandListBuilder builder)
    {
        var sqlHelper = Dependencies.SqlGenerationHelper;
        var stringMapping = Dependencies.TypeMappingSource.FindMapping(typeof(string));

        builder
            .Append("CREATE INDEX ")
            .Append(sqlHelper.DelimitIdentifier(operation.Name))
            ...
            .Append(stringMapping.GenerateSqlLiteral(...))
            .AppendLine(sqlHelper.StatementTerminator)
            .EndCommand();
    }
}

然后像使用它

 protected override void OnConfiguring(DbContextOptionsBuilder options)
   => options
        .UseSqlServer(connectionString)
        .ReplaceService<IMigrationsSqlGenerator, MyMigrationsSqlGenerator>();

推荐阅读