简体   繁体   English

实体框架映射多级属性

[英]Entity Framework map multiple level properties

I am trying to implement a hierarchical inheritance structure in Entity Framework, specifically for settings. 我正在尝试在Entity Framework中实现分层继承结构,特别是对于设置。 For example, lets say we have user preferences: 例如,假设我们有用户首选项:

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
}

I'd like it so that if I lookup the user's preferences. 我想要它,以便如果我查找用户的首选项。 If the user doesn't exist or the property value is null, it looks up the parent (store) default preferences. 如果用户不存在或属性值为null,则它将查找父(存储)默认首选项。

Ideally, i'd like it to work similar to abstract inheritance: 理想情况下,我希望它的工作方式类似于抽象继承:

public class UserPreference : StorePreference {
    private string _backgroundColor;

    public string BackgroundColor {
        get { 
           if (this._backgroundColor == null)
              return base;

           return this._backgroundColor;
        } 
        set { this._backgroundColor = value; }
    }
}

If I were to write this as a SQL query, it'd be a CROSS APPLY with a CASE statement: 如果我将其编写为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

Is there a way I can achieve loading this in EF? 有什么办法可以将其加载到EF中?

In your base class add default property values: 在基类中添加默认属性值:

public class Preference {
    public string BackgroundColor { get; set; } = "Red";
    public ContactMethod ContactMethod { get; set; } = ContactMethod.SMS;
}

Something like this to set from database: 可以从数据库中设置以下内容:

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; }
}

As long as the properties are public, entity won't have a problem pulling the data from another table as the default. 只要这些属性是公共属性,实体就不会从默认情况下从另一个表中提取数据时遇到问题。 You would need to create a private field to hold the data if you used a setter: 如果使用了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; }
}

This is just an alternative to a constructor, if you need more control over the setter logic, otherwise Austin's answer would be simpler to implement 如果您需要对setter逻辑进行更多控制,则这只是构造方法的替代方法,否则Austin的答案将更易于实现

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM