-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Alternate Keys on Derived Types (TPT/TPH) #2611
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hello! Are there any workarounds equivalent to this feature? Cross-posting my question in stackoverflow which I think can be solved with this feature. Given the following classes that models a TPT inheritance using EF Core 5: public abstract class Entity
{
public int Id { get; set; }
public int PartitionId { get; set; }
public Company Company { get; set; }
}
public class Employee : Entity { }
public class Company : Entity { } How can the I tried the following public class MyContext : DbContext
{
public MyContext(DbContextOptions options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Company>().ToTable("Company");
modelBuilder.Entity<Employee>().ToTable("Employee");
modelBuilder.Entity<Entity>().ToTable("Entity");
modelBuilder.Entity<Entity>(b =>
{
b.HasOne(e => e.Company)
.WithMany()
.HasForeignKey(e => e.PartitionId)
.HasPrincipalKey(c => c.PartitionId);
});
}
} which works as expected when reading data. e.g: MyContext ctx = ...;
ctx.Set<Employee>().Include(_ => _.Company).ToList(); is correctly translated to SELECT [e].[Id], [e].[PartitionId], [t].[Id], [t].[PartitionId]
FROM [Entity] AS [e]
INNER JOIN [Employee] AS [e0] ON [e].[Id] = [e0].[Id]
INNER JOIN (
SELECT [e1].[Id], [e1].[PartitionId]
FROM [Entity] AS [e1]
INNER JOIN [Company] AS [c] ON [e1].[Id] = [c].[Id]
) AS [t] ON [e].[PartitionId] = [t].[PartitionId] But I'm getting an exception when writing data. e.g.: MyContext ctx = ...;
// company 1
ctx.Set<Company>().Add(new Company { PartitionId = 1 });
ctx.Set<Employee>().AddRange(new Employee { PartitionId = 1 }, new Employee { PartitionId = 1 }); // exception here
// company 2
ctx.Set<Company>().Add(new Company { PartitionId = 2 });
ctx.Set<Employee>().AddRange(new Employee { PartitionId = 2 }, new Employee { PartitionId = 2 });
ctx.SaveChanges();
Thanks in advance! |
@gojanpaolo I think I have a similar problem. I'm not sure if this is related to this issue, but your comment seems related. |
please add them there's a relevant use case it's when you need a composite (alternate) key in a relationship that includes the derived type. |
My use case for this, I wanted to be able to reuse the same properties across 2 entities (though they're actually more value objects) along with some specific properties for each derived type. I can use an interface to achieve this, but you still need to implement the interface and all the properties it brings, so you end up with a lot of duplicate looking code, compared to an abstract class where your derived classes only have the properties specific to them. Example interface approach: interface ISomeProps
{
string Prop1 { get; set; }
string Prop2 { get; set; }
}
class ClassA : ISomeProps
{
public string ClassASpecificProp { get; set; }
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
class ClassB : ISomeProps
{
public string ClassBSpecificProp { get; set; }
public string Prop1 { get; set; }
public string Prop2 { get; set; }
} Example abstract approach: abstract class SharedProps
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
class ClassA : SharedProps
{
public string ClassASpecificProp { get; set; }
}
class ClassB : SharedProps
{
public string ClassBSpecificProp { get; set; }
} In this case, I find the abstract class approach more concise. |
When using inheritance, we should allow "candidate" keys on derived types. For example
The text was updated successfully, but these errors were encountered: