Механизм гибких свойств

#c# #sql-server #entity-framework #ef-code-first

#c# #sql-сервер #сущность-фреймворк #ef-код-первый

Вопрос:

Допустим, у меня есть класс под названием Expense . Я могу добавить различные виды расходов, связанных с автомобилем — расходы на заправку, расходы на ремонт, билеты и т.д. Некоторые свойства расхода одинаковы для всех типов, таких как стоимость, дата и т.д., Но есть некоторые различия. Например: когда я заправляю свой автомобиль, я хочу сохранить информацию, например, полностью ли я заправил свой бак или нет. Однако, когда я сохраняю восстановление, я хочу сохранить некоторую другую информацию.

Проблема в том, как создать какой-то механизм гибких свойств?

То , что я придумал , — это иметь две таблицы: expenses и expenses_properties . В expenses таблице я мог бы хранить все основные, общие данные и expenses_properties имел бы следующую структуру:

 | Id | PropertyName | PropertyValue | ExpenseId
|  1 | IsFull       | "true"        |     1
|  2 | Stuff        | "2016-10-02"  |     1
  

Проблема в том, что для PropertyValue столбца мне пришлось бы использовать определенный тип, например nvarchar , например. В этом случае я не смог бы правильно отсортировать эти значения (например, по дате)? Или, может быть, я бы так и сделал?

Я думаю, что должен быть лучший способ сделать это, используя подход Entity Framework Code First.

Комментарии:

1. Если вы знаете официальный термин для этого — значение атрибута сущности , вы можете провести некоторые дальнейшие исследования. Я уверен, что это заставит вас дважды подумать.

2. @Герт, большое тебе спасибо! Исследование действительно заставило меня дважды подумать!

Ответ №1:

Я бы сначала создал вашу модель класса / объекта (а не наоборот, т. Е. Начиная с базы данных):

 public abstract class ExpenseBase 
{
    public DateTime ExpenseDate { get; set; }
    public double Cost { get; set; }
}

public class FuelExpense : ExpenseBase
{
    public  Boolean FilledUp { get; set; }
}

public class OtherExpense : ExpenseBase
{
    public string SomeOtherProperty { get; set; }
}
  

Затем выберите стратегию сопоставления наследования. В этой ситуации я обычно использую «Таблицу для каждого конкретного класса» (TPC).

Ответ №2:

Если существуют разные типы расходов, то на самом деле имеет смысл иметь разные классы (т.Е. Разные таблицы). У вас может быть Expenses место, где вы можете хранить общие данные, а затем TankExpense место, где вы храните определенные «свойства» со столбцом ExpenseId , который может быть внешним ключом идентификаторов таблицы расходов. Когда вам нужно получить экземпляр expense, вы просто извлекаете if с помощью EF, и появятся все связанные с этим расходы:

 if (myExpense.TankExpense.Length > 0)
{
    var isFull = myExpense.TankExpense[0].Full;
}