如何扩展dll中存在的EF实体? 我希望能够创建一个引用该DLL的新项目,并且能够添加属性和相关实体,而无需更改原始dll。
dll尚未编译,因为我们处于项目的早期阶段,但我们希望保留所有内容,以便我们以后可以扩展它们。
我们可以修改数据库以添加新属性。
我们正在构建一个具有核心功能(安全性,菜单,审核)的基础(或平台)项目,我们正在将其包含在dll中,我们将其作为使用其他项目的起点。 我们的场景类似于this和this,但我们使用的是数据库优先方法,因此这里提出的解决方案似乎并不适用。 (如果我错了请纠正我。)
如果没有dll限制,如果我们想添加一个新属性,我们只需在db中添加该列,重新生成模型,然后添加并映射该属性。但是,由于我们想让平台dll关闭,事情并不那么容易。
特别是,我们希望能够扩展用户实体,例如,添加几个varchar列,并向新实体添加关系(Marital Status)。我们还使用了预先加载,因此我们还需要使用Include
来获取新属性。
以下是生成的用户实体:
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; }
}
总结了这个场景。
我试过通过继承来扩展实体: 创建了一个新的测试模型,映射到与原始dll相同的db,然后我在db中添加了新属性。作为一个例子,我添加了一个属性婚姻状态,它映射到一个新实体,该实体说明用户是否已结婚,单身,离婚。我将修改后的表映射到名为“MaritalUser”的实体。手动修改类,删除重复的东西并将其设置为从旧用户继承:
public partial class MaritalUser : SDK.DAL.Model.User
{
public Nullable<int> maritalStatusId { get; set; }
public virtual MaritalStatus MaritalStatus { get; set; }
}
到目前为止,旧项目工作正常,新列没有问题,它们被忽略了。在新项目中,我可以获得扩展用户,如果我使用新类,我可以使用预先加载来加载MaritalStatus实体。然而,我无法加载加载角色,例如(基类的属性),因为我得到例外:A specified Include path is not valid. The EntityType 'MaritalUser' does not declare a navigation property with the name 'Role'.
通常,EF不支持在基本类型中定义的属性包含。我无法解决这个问题。
然而,我可以编辑连接字符串以包含来自两个edmx文件的资源,如下所示:
<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="data source=...;multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" />
这允许新上下文重用旧上下文中的东西,我可以查询这两种类型。虽然它们在db中是相同的,但是上下文需要单独处理它们。 到目前为止,我能想到的最好的是,编辑获取用户的所有方法,并在其中获取两种类型,将它们合并到派生类中并返回。
这是我能得到的最好的吗?有更优雅的解决方案吗?
修改 为了澄清,我们要添加到实体的新属性将映射到数据库中的新列。部分类不是一个选项,因为我们需要在dll关闭后扩展。