Entity Framework DB-First, implement inheritance
One possible way is to use one table for each type called TPT (table-per-type), which I prefer to use. To achieve this, you define your tables like the model shown in the following picture:
Note that the relationships between child and base entity are one-to-one on their pk columns, and all common fields are moved to the base table. After creating your tables, right click on the models page in your visual studio, and select Update Model from Database..., and then in the add tab, select these 3 tables to add. At first you should see this model diagram, which needs to be changed a bit:
Do these steps for Person
and Organization
separately:
- Right click on entity and select Properties
- In the Base Type property select
Identity
- Select and then delete the association between this entity and
Identity
- Select and then Delete the PK (ID column) of this entity (Inherits from base entity)
After these steps save your model. Now your model should look like this:
Now compile your project and enjoy your life!
Additional resources:
Entity Framework Designer TPH Inheritance
Database first , How to implement inheritance in EF6
I would suggest that database inheritance/TPT/TPH is not necessary for this situation. What you need is just an IAuditable
interface:
public interface IAuditable
{
string CreatedBy { get; set; }
DateTimeOffset CreatedTime { get; set; }
string ModifiedBy { get; set; }
DateTimeOffset? ModifiedTime { get; set; }
}
Then you have two options:
If you are sure all of your entities will be
IAuditable
, you can simply change the T4 template so that all auto-generated entities will implementIAuditable
.If only some of your entities will be
IAuditable
, you can add partial classes to those auditable entities like:public partial class Foo
{
// Auto-generated properties by EF
public int Id { get; set; }
...
}Then in another file:
public partial class Foo : IAuditable
{
// No implementation because auditable fields already exists
}
You can then derive an abstract class from DbContext
to automatically update these IAuditable
properties:
public abstract class AuditableDbContext : DbContext
{
public override int SaveChanges()
{
UpdateAuditableProperties();
return base.SaveChanges();
}
public override async Task<int> SaveChangesAsync()
{
UpdateAuditableProperties();
return await base.SaveChangesAsync();
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
{
UpdateAuditableProperties();
return await base.SaveChangesAsync(cancellationToken);
}
protected virtual void UpdateAuditableProperties()
{
var now = DateTimeOffset.Now;
var userName = GetUserName();
var changedAuditableEntities = from entry in ChangeTracker.Entries<IAuditable>()
let state = entry.State
where
state.HasFlag(EntityState.Added) ||
state.HasFlag(EntityState.Modified)
select entry;
foreach (var auditable in changedAuditableEntities)
{
var entity = auditable.Entry;
switch (auditable.State)
{
case EntityState.Added:
entity.CreatedDate = now;
entity.CreatedBy = userName;
break;
case EntityState.Modified:
entity.ModifiedDate = now;
entity.ModifiedBy = userName;
break;
}
}
}
protected abstract string GetUserName();
}
Your DbContext
can derive from AuditableDbContext
and then implement GetUserName()
to supply the username who creates/modifies the entities.
Entity Framework Database first How to alter entities to make them derive from a base class
What you are looking for is something similar to TPH (http://msdn.microsoft.com/en-us/data/jj618292.aspx)
I don't think this will work for you however, as you have multiple existing tables.
One of the possible solutions is:
- Create a base class called "BaseModel" (or something like that)
- Add those properties as abstracts to force them to be overridden
- Create a method in that base class to populate those fields, or create a helper which takes BaseModel, IsDeleted,LastUpdated, LastUpdatedUser as a parameter and update the model.
- Extend the partial classes generated by the model.tt file and inherit from the BaseModel class.
Thanks,
Dave
EntityFramework code-first inheritance with eager include relationship on derived class
This is now supported in EF Core 2.1. Now to see if the resulting query is not too much performance-hungry.
Related Topics
How to Implement One "Catch'Em All" Exception Handler with Resume
Reading Fromuri and Frombody at the Same Time
Httpwebrequest Times Out on Second Call
Creating a Database Programmatically in SQL Server
Process Queue with Multithreading or Tasks
Show Authentication Dialog in C# for Windows Vista/7
How to Know the Repeating Decimal in a Fraction
Datagridtextcolumn Visibility Binding
Detect Swipe Gesture Direction
C# Open File, Path Starting with %Userprofile%
Is Deferred Execution in ASP.NET MVC View a Very Bad Thing
Internal .Net Framework Data Provider Error 1025
Get the Decimal Part from a Double
How to Handle Forms Authentication Timeout Exceptions in ASP.NET