programing

EF 6.1 고유 Nullable 인덱스

css3 2023. 9. 2. 08:43

EF 6.1 고유 Nullable 인덱스

EF 6.1에서는 Code First를 사용하여 엔티티의 속성을 사용하거나 다음과 같이 유창한 API를 사용하여 인덱스를 만들 수 있습니다.

 Property(x => x.PropertyName)
                .IsOptional()
                .HasMaxLength(450)
                .HasColumnAnnotation("Index",
                    new IndexAnnotation(new IndexAttribute("IX_IndexName") {IsUnique = true,  }));

라고 할 수 있는 방법이 있습니까?WHERE PropertyName IS NOT NULLSQL Server에서 기본적으로 사용하는 것과 동일한 방식으로 사용할 수 있습니다(https://stackoverflow.com/a/767702/52026) 참조).

나는 EF에게 이 where 절을 사용하라고 말할 방법을 찾지 못했지만 여기 몇 가지 해결책이 있습니다.케이스에 맞는지 확인합니다.

  1. 엔티티 프레임워크 설치, DbContext 정의, 엔티티 정의, app.config의 연결 문자열 등.
  2. 마이그레이션 사용 - 패키지 관리자 콘솔 '-마이그레이션 사용'에서 실행
  3. DbMigration 생성 - Package Manager 콘솔 'Add-MigrationMigrationName'에서 실행
  4. 된 "에서 된 DbMigration Up메서드는 고유한 null 가능 인덱스를 만들기 위해 sql을 실행합니다.

코드:

// Add unique nullable index 
string indexName = "IX_UQ_UniqueColumn";
string tableName = "dbo.ExampleClasses";
string columnName = "UniqueColumn";

Sql(string.Format(@"
    CREATE UNIQUE NONCLUSTERED INDEX {0}
    ON {1}({2}) 
    WHERE {2} IS NOT NULL;",
    indexName, tableName, columnName));

참고: 다운그레이드도 만드는 것을 잊지 마십시오.DownDropIndex내부 메서드:

DropIndex(tableName, indexName);

또한 데이터베이스에 고유한 인덱스 제약 조건과 충돌할 수 있는 데이터가 이미 있는 경우 추가 코드가 필요할 수 있습니다.

참고: 여기서는 CreateIndex 메서드를 사용할 수 있지만 올바른 인덱스를 만들 수 없습니다.EF는 제 익명의 주장을 무시하거나 제가 잘못 적었습니다.당신이 직접 해보고 여기에 당신의 결과와 함께 쓸 수 있습니다.구문은 다음과 같습니다.

CreateIndex(
    table: "dbo.ExampleClasses",
    columns: new string[] { "UniqueColumn" },
    unique: true,
    name: "IX_UniqueColumn",
    clustered: false,
    anonymousArguments: new
    {
        Include = new string[] { "UniqueColumn" },
        Where = "UniqueColumn IS NOT NULL"
    });

5 고유 열 및 기타 동일한 값에 대해 null 값을 가진 두 개의 시도를 추가합니다.

여기 내 데모 코드가 있습니다 - Pastebin

EF Core에서는 Fluent API에서 HasFilter 메서드를 사용하여 마이그레이션에 사용자 지정 SQL을 추가하지 않고도 원하는 작업을 수행할 수 있습니다.

builder.Entity<Table>()
    .HasIndex(x => x.PropertyName)
    .HasName("IX_IndexName")
    .HasFilter("PropertyName IS NOT NULL");

이렇게 하면 다음과 같은 마이그레이션이 생성됩니다.

migrationBuilder.CreateIndex(
    name: "IX_IndexName",
    table: "Table",
    columns: new[] { "PropertyName" },
    filter: "PropertyName IS NOT NULL");

아니요, 기본적으로 할 수 없습니다.

그러나 다음을 지원하는 사용자 정의 SQL 생성기를 만들었습니다.

  1. 의 합니다.ASC또는DESC
  2. 를 사용할 수 있습니다.WHERE

사용하려면 인덱스 이름만 수정해야 합니다.이름은 다음과 같이 3개의 부분으로 구분됩니다.:부품은 다음과 같습니다.

  1. 인덱스 이름
  2. 주문 정렬
  3. where 절

2개의 열에 인덱스가 있는 경우 다음과 같이 하십시오.Column1ASC그리고.Column2 DESC그리고 필요합니다.where인덱스 이름은 다음과 같습니다.

var uniqueName = "UN_MyIndex:ASC,DESC:Column1 IS NOT NULL";

이렇게 간단히 사용할 수 있습니다.

Property(t => t.Column1)
            .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute(uniqueName) { IsUnique = true, Order = 1 }));

Property(t => t.Column2)
            .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute(uniqueName) { IsUnique = true, Order = 2 }));

러면에서 당의신.Configuration.cs이합니다. " " " "라는 이름의 파일입니다.

SetSqlGenerator("System.Data.SqlClient", new CustomSqlServerMigrationSqlGenerator());

마지막으로 다음을 생성합니다.CustomSqlServerMigrationSqlGenerator.cs표시된 대로 파일: 여기 코드.

Viktor의 답변을 바탕으로 자동으로 이 코드를 생성하는 솔루션을 생각해냅니다.

최종 마이그레이션 파일은 사용할 수 없습니다.CreateIndex내가 이름 붙인 방법 말고는.CreateIndexNullable내가 만든 이 메서드는DbMigrationEx연장되는DbMigration

protected void CreateIndexNullable(string table, string column, string name)
{
    Sql($@"CREATE UNIQUE NONCLUSTERED INDEX [{name}] ON {table}([{column}] ASC) WHERE([{column}] IS NOT NULL);");
}

마이그레이션 클래스 코드를 변경하는 방법은 무엇입니까?

Configuration설정한 마이그레이션 폴더에 생성된 클래스

CodeGenerator = new CSharpMigrationCodeGeneratorIndexNullable();

나의CSharpMigrationCodeGeneratorIndexNullable클래스 확장CSharpMigrationCodeGenerator저는 정확한 수업 내용을 보여주지 않고 아이디어만 발표하겠습니다.기준CSharpMigrationCodeGenerator내용이 일부 메서드를 오버라이드했습니다.Entity Framework 프로젝트는 https://github.com/aspnet/EntityFramework6 에서 이용할 수 있습니다.

마이그레이션 클래스를 다음으로 변경하려면DbMigrationEx방법을 사용했습니다.

Generate(IEnumerable<MigrationOperation> operations, string @namespace, string className)

변화가 필요한 유일한 것은

WriteClassStart(
    @namespace, className, writer, "DbMigration", designer: false,
    namespaces: GetNamespaces(operations));

마이그레이션 방법을 다음으로 변경하려면CreateIndexNullable방법을 사용했습니다.

Generate(CreateIndexOperation createIndexOperation, IndentedTextWriter writer)

라인을 변경해야 합니다.

writer.Write("CreateIndex(");

또한.

WriteIndexParameters(createIndexOperation, writer);

로.

writer.Write(", ");
writer.Write(Quote(createIndexOperation.Name));

그러나 인덱스가 null이어야 하는지 여부를 어떻게 알 수 있습니까?

createIndexOperation매개 변수에 인덱스 정보가 포함되어 있습니다.수정할 수 없습니다.CreateIndexOperation생성, 그러나Table,Name그리고.Columns속성은 엔티티 클래스의 필드로 이동하고 가져오기에 충분할 수 있습니다.Index확장할 수 있는 속성입니다.

EF6을 사용하면 다음과 같은 비클러스터된 고유 인덱스를 수행할 수 있습니다.

modelBuilder.Entity<T>()
                .HasIndex(index => index.Column, "idx_column_notnull")
                .IsUnique()
                .HasFilter("column IS NOT NULL")
                .IsClustered(false);

언급URL : https://stackoverflow.com/questions/24361518/ef-6-1-unique-nullable-index