7

I want create a table with a primary key shadowed (out of the model).

public class Person
{
    public string Name { get; set; }
}

public class PersonEntityTypeConfiguration : IEntityTypeConfiguration<Person>
{
    public void Configure(EntityTypeBuilder<Person> builder)
    {
        builder.Property?
        builder.HasKey("Id")????
    }
}

Note: the real case is a different class and a value object (DDD).

Jhon Duck
  • 357
  • 4
  • 14
  • Have you tried `builder.HasKey("Id");`? – DavidG Jul 24 '18 at 17:05
  • @DavidG I can't test the project, but "HasKey" expects the name of a property and I can't assign a type – Jhon Duck Jul 24 '18 at 17:10
  • @GertArnold These are tries – Jhon Duck Jul 24 '18 at 17:11
  • @JhonDuck why dont you use a DTO wrapper? I mean keep your model class with the key property as it is, make its class internal and expose a DTO that does not have the key field.. I think this approach would be easier and correct from a DDD perspective. – taquion Jul 24 '18 at 17:29
  • If you want to walk the hard path take a look to custom [conventions] (https://blogs.msdn.microsoft.com/dotnet/2016/09/29/implementing-seeding-custom-conventions-and-interceptors-in-ef-core-1-0/) and to [this](https://stackoverflow.com/a/21686896/4430204) answer – taquion Jul 24 '18 at 17:31

3 Answers3

12

There are two ways to get this done. One is to define the property and then configure it as key (the order matters)

builder.Property<int>("ID")
    .HasColumnType("int")
    .ValueGeneratedOnAdd();
builder.HasKey("ID");

You probably want ValueGeneratedOnAddhere, because it's more or less the point of shadow properties to do everything under the hood.

I never like code in which the order of statements is a hidden requirement. It may lead to unexpected bugs. I would prefer the single-statement option:

builder.Property<int>("ID")
    .HasColumnType("int")
    .ValueGeneratedOnAdd()
    .HasAnnotation("Key", 0);

The value 0 in HasAnnotation is entered because it's mandatory. It has no bearing on the key generation.

I'm not yet sure if it's a good idea to use shadow properties in keys. I can't oversee which issues may appear when actually working with them. It may be a very good idea indeed.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
3

I don't use the TypeBuilder a lot but this should be close:

public void Configure(EntityTypeBuilder<Person> builder)
{
    builder.Property<int>("id");
    builder.HasKey("Id");
}
luke
  • 36,103
  • 8
  • 58
  • 81
H H
  • 263,252
  • 30
  • 330
  • 514
0

I ran into a very similar problem. I wanted to use a shadow property as the primary key (Identity) with EF Core and none of the above worked for me.

public void Configure(EntityTypeBuilder<Person> builder)
{
      builder.Property<int>("Id")
            .HasColumnType("int")
            .UseIdentityColumn();

     builder.HasKey("Id");
}

The last statement is to make sure it is the only PK in your table, otherwise it will become an Composite with a any FK that you might also have. Hope it helps!

Matthijs
  • 1
  • 3