实体框架映射多级属性
Posted
技术标签:
【中文标题】实体框架映射多级属性【英文标题】:Entity Framework map multiple level properties 【发布时间】:2017-04-17 20:17:14 【问题描述】:我正在尝试在实体框架中实现分层继承结构,专门用于设置。例如,假设我们有用户偏好:
public class StorePreference: Preference
public class UserPreference : Preference
public class Preference
public string BackgroundColor get; set;
public ContactMethod ContactMethod get; set;
public enum ContactMethod
SMS,
Email
如果我查找用户的偏好,我会喜欢它。如果用户不存在或属性值为 null,则查找父(存储)默认首选项。
理想情况下,我希望它类似于抽象继承:
public class UserPreference : StorePreference
private string _backgroundColor;
public string BackgroundColor
get
if (this._backgroundColor == null)
return base;
return this._backgroundColor;
set this._backgroundColor = value;
如果我将其编写为 SQL 查询,它将是一个带有 CASE 语句的 CROSS APPLY:
SELECT
CASE WHEN User.BackgroundColor == null THEN Store.BackgroundColor ELSE User.BackgroundColor END BackgroundColor,
CASE WHEN User.ContactMethod == null THEN Store.ContactMethod ELSE User.ContactMethod END ContactMethod
FROM UserPreference User
CROSS APPLY StorePreference Store
WHERE UserPreference.UserId = @UserId
有没有办法可以在 EF 中加载它?
【问题讨论】:
【参考方案1】:在您的基类中添加默认属性值:
public class Preference
public string BackgroundColor get; set; = "Red";
public ContactMethod ContactMethod get; set; = ContactMethod.SMS;
从数据库中设置这样的东西:
public class StorePreference : Preference
public class UserPreference : Preference
public class Preference
public Preference()
BackgroundColor = DefaultPreference.BackgroundColor;
ContactMethod = DefaultPreference.ContactMethod;
public string BackgroundColor get; set;
public ContactMethod ContactMethod get; set;
public DefaultPreference DefaultPreference get; set;
public class DefaultPreference
public string BackgroundColor get; set;
public ContactMethod ContactMethod get; set;
【讨论】:
这硬编码默认值。我希望它们在数据库中,以便可以更改默认值 你可以让 Preference 默认它自己的对象,比如DefaultPreference
,然后在构造函数中设置默认值吗?
我刚刚更新了答案以反映一个 DefaultPreference 对象,如果您希望它与数据库分开,则该对象必须分开。
这将使 UserPreference
使用来自 Preference
的值而不是 StorePreference
如果它为 null 并且如果用户的记录在 UserPreference 表中不存在则不回答问题
因此,您似乎正在寻找具有单个属性的自动魔术解决方案,或者在检查 null 时基于另一个表设置数据库值的东西,包括让新对象甚至不存在,直到节省时间才真正从数据库中获取默认值?您将不得不编写一些代码来在类外实现这一点。没有自动化的 EF 解决方案可以实现这一目标。您是否有其他一些可以参考的框架或语言来满足您的要求,并且您正在寻找与之等效的东西?【参考方案2】:
只要属性是公共的,实体默认从另一个表中提取数据就不会出现问题。如果您使用 setter,则需要创建一个私有字段来保存数据:
public class ChildTable : EntityBase
private string _someCategory;
[Key]
[Column(name: "CHILD_ID")]
public override int Id get; protected set;
[Column(name: "SOME_CATEGORY")]
public string SomeCategory
get return _someCategory;
set _someCategory = value ?? ParentTable.SomeCategory;
[ForeignKey("ParentTable")]
[Column(name: "PARENT_ID")]
public int ParentTableId get; set;
public virtual ParentTable ParentTable get; set;
这只是构造函数的替代方案,如果您需要更多地控制设置器逻辑,否则奥斯汀的答案会更容易实现
【讨论】:
以上是关于实体框架映射多级属性的主要内容,如果未能解决你的问题,请参考以下文章
在实体框架中将对象类型属性映射到 varbinary(MAX)