Reputation: 10547
I'm attempting to map to a lookup table that contains values for multiple tables. I cannot modify the database. The table has a one-to-many relationship with multiple tables, but no foreign key constraints. The lookup table has three columns code
, category
and description
. A sample set of the data would look like this:
Lookup table:
code | category | description |
---|---|---|
1 | Role | Admin |
2 | Role | User |
1 | Job | Mechanic |
2 | Job | Plumber |
3 | Job | Electrician |
1 | Activity | Work |
2 | Activity | Overtime |
3 | Activity | Training |
I'm interested in joining the Activity
table that looks like this (some columns omitted for clarity):
Activity table:
id | code | hours |
---|---|---|
1 | 1 | 8.0 |
2 | 1 | 8.0 |
3 | 2 | 1.0 |
4 | 2 | 5.3 |
I want to join the Activity
table to the Lookup
table using EF Core. If I was writing a SQL statement I'd just have something like this:
SELECT *
FROM Activity
JOIN Lookup ON Lookup.code = Activity.code
AND Lookup.category = 'Activity'
So in EF Core I created my classes to represent my tables:
public class Lookup
{
[Key]
public string Code { get; set; }
public string Category { get; set; }
public string Description { get; set; }
}
public class Activity
{
[Key]
public string Id { get; set; }
public string Code { get; set; }
public double Hours { get; set; }
[NotMapped]
public string LookupCategory { get; set; } = "Activity";
public Lookup ActivityType { get; set; }
}
I also have the following fluent relationship setup:
modelBuilder.Entity<Activity>()
.HasOne<Lookup>(x => x.ActivityType)
.WithMany()
.HasForeignKey(x => x.Code);
But this doesn't work since there are multiple rows with the same code
value. How do I get the key constraint to also take in to account the LookupCategory
value since it is not mapped?
Upvotes: 2
Views: 2648
Reputation: 10547
Following pjs's suggestions I was able to implement the following successfully:
I created a new class that extended Lookup
. This class has the attribute NotMapped
, which was an important part in getting everything to finally work.
[NotMapped]
public class ActivityType : StaffLookup{ }
In Activity
I modified the class to use ActivityType
instead of StaffLookup
. I also removed the LookupCategory
property
public class Activity
{
[Key]
public string Id { get; set; }
public string Code { get; set; }
public double Hours { get; set; }
// This is mapped to our subclass so that we can get the filtered values
public ActivityType ActivityType { get; set; }
}
In my OnModelCreating
I removed the existing fluent relationship and added the following new ones:
// This tells EF what column is used as a the filter
modelBuilder.Entity<StaffLookup>()
.HasDiscriminator(x => x.Category);
// This is what filters the Lookup table for us
modelBuilder.Entity<ActivityType>()
.HasDiscriminator()
.HasValue("Activity");
// Since the foreign key isn't mapped in the database
// we need to add this relationship
modelBuilder.Entity<ActivityMain>()
.HasOne(x => x.ActivityType)
.WithMany()
.HasForeignKey(x => x.ActivityCode);
Upvotes: 3
Reputation: 383
Look at setting up a Table-Per-Hierarchy, TPH, with Category as the discriminator. Then your EF model can have Lookup as the base table, with RoleType, ActivityType, etc. as child entities in your EF model. The relationship would be from ActivityType to Activity, and EF would already know that the only applicable values in ActivityType are the Lookup rows with Category = 'Activity'. You would want to verify all existing data meets those constraints since they aren't enforced in the database.
Upvotes: 2