We have a ‘base’ DbContext that defines a object model with some entities and relationships. This DbContext maps to a sql server database. This DbContext is ‘packaged’ into a separate assembly, available for other projects (as a kind of data access layer).
We use ‘code first’ approach.
Part of base context definition could be the following:
public class Blog
{
public int Id { get; set; }
public DateTime CreationDate { get; set; }
//...
}
public class DataContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
//...
}
We would like to define an extended version of base DbContext, for example adding new entities but also extending some existing entities with new properties.
So, in a new project, we reference the ‘packaged’ base context (dll reference) and starts defining new data context and new entities like so:
public class ExtendedBlog : Blog
{
public int? NewProp { get; set; }
//...
}
where Blog is an entity type already defined in base context
we want to ‘substitute’ base Blog type with new type, so we define the entity set in the following way:
public class ExtendedDataContext : BaseDataContext
{
public new DbSet<ExtendedBlog> Blogs { get; set; } //using new keyword to replace existing definition
}
We also defined a mechanism, using reflection, capable of extending the method OnModelCreating, to extend data context definition using fluent api.
We can use TPH or TPT hierarchy strategy for inheriting entity types.
Our problem:
Every base/existing entity that has a relationship with Blog, should have a property like Blog blog or ICollection blogs.
Because we define a new type to extend base type (ExtendedBlog is a new type) and because we only re-define Blogs DbSet, ‘related’ entities still reference base type and don’t ‘sees’ new properties of ExtendedBlog.
We can’t, for example, write a query that apply a filter based on new properties of ExtendedBlogType.
To correct the issue, we should also extend every entity that is in relationship with extended one; and, if entities in relationship has others relationships, the ‘override’ should expand to a lot of entities.
It seems that this is not the proper way to extend a DbContext.
Ideally, using partial classes, should accomplish our requirement because we can ‘add’ properties maintaining original type. Partial class construct can be applied only in the same project.
We also checked ‘shared projects’ approach but it is only supported by Visual Studio (no Visual Studio code) and requires sharing source code (we don’t want to share source code).
Something like extension methods, applied to properties, may solve the problem but this feature is not available; in addition, EF seems to only map properties and there is no way to map, for example, getter+setter methods some table fields.
Any suggestion?
Thanks.
2
Answers
You can use generics to specify the extended class to use as your blog entities. You specify the generic type in the
BaseDataContext
class. It can look like this:In your other project, you can use the
ExtendedBlog
class for your new/extended blog entity like this in your new data context:Your other entities must use the generic type
TBlog
as well to reference the specific blog entity type. As an example you might have tags for a blog and that entity can look like this:Try my Answer