How to create composite unique constraint on multiple value objects

Viewed 155

I need to create a unique constraint on multiple fields, and those fields are ValueObjects.

Let's say I have this

public class MyEntity 
{
   public EntityCode Code {get;set;}
   public SecondaryCode Second {get;set;}
}

public class EntityCode : ValueObject<string>
{
   public string Value {get;set;}
   public string Description {get;set;}
}

public class SecondaryCode: ValueObject<string>
{
   public string Value {get;set;}
   public string Description {get;set;}
}

I can create a unique constraint like this

public class MyEntityConfiguration : EntityTypeConfiguration<MyEntity>
{
   ...


   builder.OwnsOne(p => p.Code)
       .HasIndex(p => p.Value)
       .IsUnique()

   ...
}

But I would like a composite key and I can't figure out how to do this with value object. Take a look at this sample, it is not working as I expected


  builder.OwnsOne(p => p.Code);
  builder.OwnsOne(p => p.Second);

  builder
       .HasIndex(p => new { p.Code.Value, p.Seconde.Value })
       .IsUnique()

Any help would be appreciated

1 Answers

A key serves as a unique identifier for each entity instance. Most entities in EF have a single key, which maps to the concept of a primary key in relational databases. You can also configure multiple properties to be the key of an entity - this is known as a composite key.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    builder.Entity<MyEntity>()
           .HasKey(p => new { p.Code.Value, p.Seconde.Value });
}

Composite keys can only be configured using the Fluent API, conventions will never set up a composite key, and you can not use Data Annotations to configure one.

To create this composite primary key with these two columns, override DbContext.OnModelCreating(). This method is called when the model for a derived context has been initialized, but before the model has been locked down and used to initialize the context.

public class MyDbContext : DbContext
    {
        // Normal DbContext stuff here
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
           builder.Entity<MyEntity>()
           .HasKey(p => new { p.Code.Value, p.Seconde.AnotherValue });
        }
    }

after that generate the migration and update database.

Related