I have to extend current database entity (Foo
) to include new fields. Sounds easy but I struggle with solution. Problem is, I'm not able to create a partial class for Foo
because it's part of a dll which I'm using. And there is no way how I could request modify Foo
(or do it by my own) as I wish.
My project structure is similar to this:
// unmodifiable because part of dll
class Foo
{
int Id { get; set; }
string Name { get; set; }
}
// unmodifiable because part of dll
interface IFooContext
{
DbSet<Foo> Foo { get; set; }
}
class FooContext: DbContext, IFooContext
{
DbSet<Foo> Foo { get; set; }
}
With my limited knowledge of .net, what I tried, was create class Bar
what extends Foo
and expected it would be enough to implement IFooContext
with extended class Bar
.
Below you can see, but it will end up with error, because C# doesn't allow use extended class interchangeable for parent.
class Bar: Foo
{
string Description { get; set; } //new field
}
class FooLoader: DbContext, IFooContext
{
DbSet<Bar> Foo; //error because DbSet<Foo> required
}
What I could do, is create property DbSet<Bar> Bar { get; set; }
inside FooLoader
, but then I will end up with two almost identical database tables: Foo and Bar.
So I made modification and created class Bar
which will contain FooId
. It results into two tables, where Bar
table has a reference to Foo
.
class Bar
{
int Id { get; set; }
Foo Foo { get; set; }
int FooId { get; set; }
string Description { get; set; }
}
Both cases, will create a new table what I'm not sure, if is what I looking for. But is there any other way how to do it and have new fields included in base class/table?
Code first approach gives you at least 3 options to map your (inheritance hierarchy) entities to tables:
What you need is the 1st approach, which will map your base class and hieratances to one table, but an additional column ("Discriminator" as default name) will be added to identify their Type
, which column will be used to revert to its own type when you query the full row from database. and most important: the 1st approach also gives best performance, comparing the other 2 approachs.
here are good posts where you can find implementation:
it is simply like this:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
....
modelBuilder.Entity<Foo>()
.HasDiscriminator<string>("FooType")
.HasValue<Foo>(nameof(Foo))
.HasValue<Bar>(nameof(Bar))
.HasValue<Other>(nameof(Other));
...
base.OnModelCreating(modelBuilder);
}
or
modelBuilder.Entity<Foo>()
.HasDiscriminator<int>("FooType")
.HasValue<Foo>(1)
.HasValue<Bar>(2)
.HasValue<Other>(3);