1

How can I extend an EF entity that is present in a dll? I would like to be able to create a new project that references that dll and be able to to add properties and related entities without needing to alter the original dll.

The dll is not compiled yet, as we are in early stages of our project, but we want to leave everything ready so that we can extend them later on.

We can modify the database to add new properties.

We are building a base (or platform) project with core functionality (security, menus, auditing) and we're in the process of wrapping it up in dlls, that we'll use as starting point for using other projects. Our scenario is similar to this and this, but we're using database first approach, so the solutions proposed there don't seem to apply here. (correct me if I'm wrong please).

Without the dll restriction, if we wanted to add a new property, we would just add the column in the db, regenerate the model, and presto, the property is added and mapped. But as we want to leave the platform dll closed, things aren't so easy.

In particular, we'd like to be able to extend the user entity, for example, adding a couple of varchar columns, and adding a relationship to a new entity (Marital Status). We also use eager loading, so we also need to use Include to get the new properties.

Here is the generated user entity:

public partial class User
{
    public User()
    {
        this.Auditoria = new HashSet<Auditoria>();
        this.UserPermission = new HashSet<UserPermission>();
        this.UserPositionLog = new HashSet<UserPositionLog>();
    }

    public int userId { get; set; }
    public string username { get; set; }
    public string password { get; set; }
    public Nullable<System.DateTime> lastActivityDate { get; set; }
    public Nullable<System.DateTime> lastLoginDate { get; set; }
    public Nullable<System.DateTime> lastPasswordChangedDate { get; set; }
    public System.DateTime creationDate { get; set; }
    public bool isLockedOut { get; set; }
    public Nullable<System.DateTime> lastLockedOutDate { get; set; }
    public int failedPasswordAttemptCount { get; set; }
    public Nullable<int> roleId { get; set; }
    public string email { get; set; }
    public bool active { get; set; }
    public bool admin { get; set; }
    public string name { get; set; }
    public string devicePIN { get; set; }
    public string sessionToken { get; set; }
    public string appVersionNumber { get; set; }

    public virtual ICollection<Auditoria> Auditoria { get; set; }
    public virtual Role Role { get; set; }
    public virtual ICollection<UserPermission> UserPermission { get; set; }
    public virtual ICollection<UserPositionLog> UserPositionLog { get; set; }
}

That sums up the scenario.

I have tried extending the entity by inheritance: Created a new test model, that is mapped to the same db as the original dll, then I added the new properties in db. As an example, I added a property marital status, which maps to a new entity that says if the user is married, single, divorced. I map the modified table to entity named "MaritalUser". Modify the class by hand, remove duplicate stuff and set it to inherit from the old user:

public partial class MaritalUser : SDK.DAL.Model.User
{
    public Nullable<int> maritalStatusId { get; set; }

    public virtual MaritalStatus MaritalStatus { get; set; }
}

So far, the old project works ok, no problems with the new columns, they are ignored. In new project I can get the extended user, and if i use the new class, i can use eager loading to load up the MaritalStatus entity. I cannot however do eager loading to load the role, for example (property of base class), as i get the exception: A specified Include path is not valid. The EntityType 'MaritalUser' does not declare a navigation property with the name 'Role'.

Aparently EF does not support includes of properties defined in base types. I could not get around this issue.

I could however edit the connection string to include resources from both edmx files like so:

<add name="SampleEntities" connectionString="metadata=res://*/DAL.Model.BackendEntities.csdl|res://*/DAL.Model.BackendEntities.ssdl|res://*/DAL.Model.BackendEntities.msl|res://*/SampleEntities.csdl|res://*/SampleEntities.ssdl|res://*/SampleEntities.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=...;multipleactiveresultsets=True;application name=EntityFramework&quot;" providerName="System.Data.EntityClient" />

This allows the new context to reuse stuff from the old context, and I can query both types. Although they are the same in db, the context needs to treat them separately. So far the best I could come up was this, to edit all the methods that get a user, and in them get both types, merge them up in the derived class and return that.

Is this the best I can get? Is there a more elegant solution?

Edit: Just to clarify, the new properties that we want to add to the entity will be mapped to new columns in database. Partial classes are not an option because we need to extend after the dll is closed.

Community
  • 1
  • 1
Miguel Hughes
  • 117
  • 12
  • possible duplicate of [Is it possible to have two partial classes in different assemblies represent the same class?](http://stackoverflow.com/questions/647385/is-it-possible-to-have-two-partial-classes-in-different-assemblies-represent-the) – Erik Philips Mar 06 '14 at 15:12
  • `Aparently EF does not support includes of properties defined in base types. I could not get around this issue.` -> There is no work around if you can't modify the original assembly (using partials). – Erik Philips Mar 06 '14 at 15:13
  • 1
    I was looking into updating the model on runtime... but there's no such possibility: http://stackoverflow.com/a/4020774/1483826. You could try recreating the edmx _before_ running your application. – mrówa Mar 06 '14 at 15:55
  • @ErikPhilips please see my edit. Partial classes are not an option as we need to extend in another dll. Would you consider removing the duplicate flag? I don't see any answers there that would help my scenario. – Miguel Hughes Mar 07 '14 at 13:19

0 Answers0