how to create index for value-object member using c# EF fluent api

Viewed 363

I have entity that contain value-object with name IdCard like this:

public class UserProfile : BaseEntity<long>
{
  public byte Gender { get; private set; } = 0;

  public int? BirthDate { get; private set; }

  public IdCard IdCard { get; set; }
}

And IdCard member like this:

public class IdCard : ValueObject
    {
        public int? Type { get; set; }

        public string No { get; set; }
    }

I need to make IdCard No as index by using EF fluent api

some thing like this

builder.HasIndex(c => c.IdCard.No);
2 Answers

Take a look at the Implement value objects from Microsoft and Using Value Objects with Entity Framework Core links. These two are helpful.

You can create UserProfileConfiguration class as follow:

public class UserProfileConfiguration : IEntityTypeConfiguration<UserProfile>
{
    public void Configure(EntityTypeBuilder<UserProfile> builder)
    {
        builder.HasKey(x => x.Id);
        builder.OwnsOne(x => x.IdCard);
        builder.HasIndex(x => x.No);
    }
}

And then, apply it in OnModelCreating method in your DbContext:

modelBuilder.ApplyConfiguration(new UserProfileConfiguration());

Ad constructor to Your IdCard that will take single parameter, in this case the No. Following should work for when the value-object have a single field that will be stored in database, so the Type would not have to be stored, but calculated after db fetch. Otherwise this would have to be stored as owned entity. Alternatively you could store Type and No together in single field and provide custom converter for those fields, but this solution would be suboptimal to say the least.

In fluent configuration, assuming that try:

modelBuilder.Entity<UserProfile>(builder =>
{
    builder.HasIndex(c => c.IdCard);
    builder.Property(p => p.IdCard)
        .HasConversion(id => id.No, value => new IdCard(value)); 
});

I do not remember if this will work in EF core without problems - there were some issues when it comes to converters used for primary keys in the past, but its worth a try.

Related