Entity Framework Coreは最初に一意の制約コードを追加します


152

属性を使用してフィールドに一意の制約を追加する方法が見つかりません:

public class User
{
    [Required]
    public int Id { get; set; }

    [Required]
    // [Index("IX_FirstAndSecond", 2, IsUnique = true)] not supported by core
    public string Email { get; set; }

    [Required]
    public string Password { get; set; }
}

私はこれらのパッケージを使用しています:

 "Microsoft.EntityFrameworkCore": "1.0.1",
 "Microsoft.EntityFrameworkCore.SqlServer": "1.0.1",
 "Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.1",
 "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",

インデックスのFluent
Michael Freidgeim

回答:


301

EFコアでは、データ注釈を使用してインデックスを作成することはできませんが、Fluent APIを使用して作成できます。

あなたの中でこれのように{Db}Context.cs

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<User>()
        .HasIndex(u => u.Email)
        .IsUnique();
}

...または、buildActionでオーバーロードを使用している場合:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<User>(entity => {
        entity.HasIndex(e => e.Email).IsUnique();
    });
}

あなたはここでそれについてもっと読むことができます:インデックス


1
あなたの助けをありがとう、それは正しい解決策です!
Vadim M

MS Identityスキーマを使用するときに機能するソリューションを探して誰かがここに来た場合は、(AspNetUsersエンティティの)電子メールではなく、NormalizedEmailフィールドに一意の制約を設定することをお勧めします。別のケースを使用すると、データベースの照合設定によっては、同じメールアドレスであっても制約に違反する可能性があります。
トム

4
このコードは文字列型の列では機能しません:(文字列列に一意の制約を追加する方法はありますか?
Johar Zaman

行くHasAlternateKey
Chamika Sandamal

1
私がこれに取り組んでいたときに私はこれを試しましたが、今これを実装する必要はありません。ところでコメントありがとうございます。@Sampath
Johar Zaman

70

また、複数の列に一意の制約を作成する場合は、これを簡単に実行できます(@Sampathのリンクをたどります)

class MyContext : DbContext
{
    public DbSet<Person> People { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>()
            .HasIndex(p => new { p.FirstName, p.LastName })
            .IsUnique(true);
    }
}

public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

9

EF Coreのソリューション

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Passport { get; set; }
}

public class ApplicationContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public ApplicationContext()
    {
        Database.EnsureCreated();
    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=efbasicsappdb;Trusted_Connection=True;");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().HasAlternateKey(u => u.Passport);
        //or: modelBuilder.Entity<User>().HasAlternateKey(u => new { u.Passport, u.Name})
    }
}

DBテーブルは次のようになります。

CREATE TABLE [dbo].[Users] (
    [Id]       INT            IDENTITY (1, 1) NOT NULL,
    [Name]     NVARCHAR (MAX) NULL,
    [Passport] NVARCHAR (450) NOT NULL,
    CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [AK_Users_Passport] UNIQUE NONCLUSTERED ([Passport] ASC)
);

EF Coreのドキュメントを参照してください


11
EF Core docsによると:If you just want to enforce uniqueness of a column then you want a unique index rather than an alternate key. In EF, alternate keys provide greater functionality than unique indexes because they can be used as the target of a foreign key.
bigworld12

:bigworld12さんのコメントへの参照docs.microsoft.com/en-us/ef/core/modeling/...
granadaCoder

3

OPは、一意のキーのエンティティクラスに属性を追加できるかどうかを尋ねています。簡単に言えば、それは可能ですが、EF Coreチームのすぐに使える機能ではありません。Entity Framework Coreエンティティークラスに属性を使用して一意のキーを追加したい場合は、ここに投稿したことを行うことができます

public class Company
{
    [Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid CompanyId { get; set; }

    [Required]
    [UniqueKey(groupId: "1", order: 0)]
    [StringLength(100, MinimumLength = 1)]
    public string CompanyName { get; set; }

    [Required]
    [UniqueKey(groupId: "1", order: 1)]
    [StringLength(100, MinimumLength = 1)]
    public string CompanyLocation { get; set; }
}

[UniqueKey]属性はMicrosoftによって定義された属性ですか?それとも自分で定義すべきですか?
Mohammed Osman

[UniqueKey]属性は、.csエンティティクラス内に(DbContextのOnModelCreating()メソッドではなく)一意のキーを追加できるようにするために開発したカスタム属性です
Justin Tubbs

3
それは素晴らしいことです。開発したカスタム属性のコードを入れていただけませんか?!
Mohammed Osman


2

これらすべての解決策を試しているが機能していない人は、これを試してみてください

protected override void OnModelCreating(ModelBuilder builder)
{

    builder.Entity<User>().Property(t => t.Email).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_EmailIndex") { IsUnique = true }));

}

2

モデル構成を介してEFコアで使用するには

public class ApplicationCompanyConfiguration : IEntityTypeConfiguration<Company>
{
    public void Configure(EntityTypeBuilder<Company> builder)
    {
        builder.ToTable("Company"); 
        builder.HasIndex(p => p.Name).IsUnique();
    }
}

1

これらのメソッドはどれも.NET Core 2.2では機能しませんでしたが、この目的で機能する別の主キーを定義するために持っていたコードを適応させることができました。

以下の例では、OutletRefフィールドが一意であることを確認したいと思います。

public class ApplicationDbContext : IdentityDbContext
    {
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Outlet>()
                .HasIndex(o => new { o.OutletRef });
        }
    }

これにより、必要な一意のインデックスがデータベースに追加されます。ただし、カスタムエラーメッセージを指定する機能はありません。


0

Fluent APIを使用して一意のキーインデックスを追加できます。以下のコードは私のために働きました

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<User>().Property(p => p.Email).HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("IX_EmailIndex") { IsUnique = true }));

    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.