Efcore: Support single configuration for all uses of an owned type, shared type, or some arbitrary base class/interface

Created on 15 Oct 2016  路  7Comments  路  Source: dotnet/efcore

Previous non core version of Entity Framework had something like this:

modelBuilder.Type<IEntity>().HasKey(e => e.Id);

I'm curious if this is planned for core version to?

I tried to implement something similar with reflection. https://gist.github.com/matjazmav/2e7335c12c55c4f6692b637bccf651bb There is only one problem with this implementation, casting object to EntityModelBuilder<TEntity> (this is marked with // TODO in the gist snippet). Anyone wan't to help me solve this?

Thanks!

punted-for-2.0 punted-for-3.0 punted-for-5.0 type-enhancement

Most helpful comment

We don't have the equivalent functionality in EF Core yet, but you can write something like this (less pretty, but does the same thing).

c# protected override void OnModelCreating(ModelBuilder modelBuilder) { foreach (var entity in modelBuilder.Model.GetEntityTypes().Where(e => typeof(IEntity).IsAssignableFrom(e.ClrType))) { modelBuilder.Entity(entity.Name).HasKey(nameof(IEntity.Key)); } }

All 7 comments

We don't have the equivalent functionality in EF Core yet, but you can write something like this (less pretty, but does the same thing).

c# protected override void OnModelCreating(ModelBuilder modelBuilder) { foreach (var entity in modelBuilder.Model.GetEntityTypes().Where(e => typeof(IEntity).IsAssignableFrom(e.ClrType))) { modelBuilder.Entity(entity.Name).HasKey(nameof(IEntity.Key)); } }

Would also allow to use modelBuilder.Owned to bulk configure owned types.
Related to #3867

The workaround mentioned above doesn't seem to be working for inherited property definitions. I have the following statement in my OnModelCreating():

foreach (var entity in modelBuilder.Model.GetEntityTypes()
  .Where(e => typeof(IEntity).IsAssignableFrom(e.ClrType)))
{
  modelBuilder.Entity(entity.Name).Property(nameof(IEntity.Uuid))
    .IsRequired().HasDefaultValueSql("NEWID()");
}

I'd expect this produce the following line in the migration for each IEntity, but it does not:

Uuid = table.Column<Guid>(nullable: false, defaultValueSql: "NEWID()")

@chrispickford It works for me in a simple test:
```C#
public interface IEntity
{
Guid Id { get; set; }
}

public class Vehicle : IEntity
{
public Guid Id { get; set; }
public string VehicleIdentificationNumber { get; set; }
}

public class VehiclePrototype : IEntity
{
public Guid Id { get; set; }
public DateTimeOffset? PressReleaseAt { get; set; }
}

public class BloggingContext : DbContext
{
private static readonly LoggerFactory Logger
= new LoggerFactory(new[] { new ConsoleLoggerProvider((_, __) => true, true) });

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseLoggerFactory(Logger)
        .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test;ConnectRetryCount=0");

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Vehicle>();
    modelBuilder.Entity<VehiclePrototype>();

    foreach (var entity in modelBuilder.Model.GetEntityTypes()
        .Where(e => typeof(IEntity).IsAssignableFrom(e.ClrType)))
    {
        modelBuilder.Entity(entity.Name).Property(nameof(IEntity.Id))
            .IsRequired().HasDefaultValueSql("NEWID()");
    }
}

}

public class Program
{
public static async Task Main()
{
using (var context = new BloggingContext())
{
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();

        context.Add(new Vehicle());
        context.Add(new VehiclePrototype());
        context.SaveChanges();
    }
}

}
```

@ajcvickers Apologies, in my haste I constructed an incorrect example. The IEntity should be an abstract class, e.g:

public abstract class Entity
{
  public int Id { get; set; }
  public byte[] RowVersion { get; set; }
  public Guid Uuid { get; set; }
}

@chrispickford Still works for me. Can you please file a new issue including a runnable project/solution or complete code listing that demonstrates the behavior you are seeing.

Consider also query filters--see #17434

Was this page helpful?
0 / 5 - 0 ratings