How to use a varchar column other than Id for PK?

asp.net-boilerplate aspnetboilerplate c# entity-framework-core primary-key

Accepted Answer

The difference is that you inherited.FullAuditedEntity<string> in which it is said thatId is the kindstring thereafter didnew alter the type toint This hiding causes a conflict for EF as a consequence.

Here's how to do it:

  1. Make use of an auto-incrementId table of typesint
  2. have a type primary key column.string
  3. have a column with a unique constraint (as requested in a relevant forum)

Code:

public class Test: FullAuditedEntity
{
    // PK
    [MaxLength(NVarcharLength14), DataType(DataType.Text)]
    public virtual string Code { get; set; }

    // Unique constraint
    public int MyUniqueId { get; set; }
}

public class AbpProjectNameDbContext : AbpZeroDbContext<Tenant, Role, User, AbpProjectNameDbContext>
{
    /* Define a DbSet for each entity of the application */    
    public DbSet<Test> Tests { get; set; }

    public AbpProjectNameDbContext(DbContextOptions<AbpProjectNameDbContext> options) : base(options) {}

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Test>().Property(t => t.Id).ValueGeneratedOnAdd(); // Auto-increment
        modelBuilder.Entity<Test>().HasAlternateKey(t => t.Id);                // Auto-increment, closed-wont-fix: https://github.com/aspnet/EntityFrameworkCore/issues/7380
        modelBuilder.Entity<Test>().HasKey(t => t.Code);                       // PK
        modelBuilder.Entity<Test>().HasIndex(t => t.MyUniqueId).IsUnique();    // Unique constraint
    }
}

produced migration

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.CreateTable(
        name: "Tests",
        columns: table => new
        {
            Code = table.Column<string>(nullable: false),
            Id = table.Column<int>(nullable: false)
                .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
            MyUniqueId = table.Column<int>(nullable: false)
        },
        constraints: table =>
        {
            table.PrimaryKey("PK_Tests", x => x.Code);
        });

    migrationBuilder.CreateIndex(
        name: "IX_Tests_MyUniqueId",
        table: "Tests",
        column: "MyUniqueId",
        unique: true);
}

Usage:

public async Task MyMethod()
{
    await _repository.InsertAndGetIdAsync(new Test
    {
        Code = "One",
        MyUniqueId = 1
    });

    // Valid
    await _repository.InsertAndGetIdAsync(new Test
    {
        Code = "Two",
        MyUniqueId = 2
    });

    try
    {
        await _repository.InsertAndGetIdAsync(new Test
        {
            Code = "One", // PK conflict
            MyUniqueId = 3
        });
    }
    catch (Exception e)
    {
    }

    try
    {
        await _repository.InsertAndGetIdAsync(new Test
        {
            Code = "Three",
            MyUniqueId = 1 // Unique constraint conflict
        });
    }
    catch (Exception e)
    {
        throw;
    }

    return null;
}

For the purpose of thoroughness, the following Stack Overflow questions are listed in order of appearance:

  1. This inquiry. (Sep 11)
  2. Getting the DeleteAsync exception "Ambiguous match found" (Sep 11) (Sep 11)
  3. Records from tables with identity columns cannot be deleted (Sep 12) (Sep 12)
  4. How can ASP.NET Boilerplate create a composite unique key? (Sep 13) (Sep 13)
1
2/12/2018 7:33:27 AM

Popular Answer

ZZZ_tmp


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow