Entity Framework отображает многоуровневые свойства
Я пытаюсь реализовать иерархическую структуру наследования в Entity Framework, специально для настроек. Например, допустим, у нас есть пользовательские настройки:
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
}
Мне бы хотелось, чтобы, если я посмотрю настройки пользователя. Если пользователь не существует или значение свойства равно нулю, он ищет настройки родительского (хранилища) по умолчанию.
В идеале мне бы хотелось, чтобы он работал аналогично абстрактному наследованию:
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-запрос, это был бы CROSS APPLY с оператором CASE:
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?
2 ответа
Пока свойства общедоступны, у объекта не будет проблем с извлечением данных из другой таблицы по умолчанию. Вам нужно будет создать личное поле для хранения данных, если вы используете сеттер:
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; }
}
Это просто альтернатива конструктору, если вам нужно больше контроля над логикой установщика, иначе ответ Остина будет проще реализовать
В вашем базовом классе добавьте значения свойств по умолчанию:
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; }
}