ASP.NET Core 2: Каким может быть код, лежащий в основе отношения «многие к одному» в этом случае? - PullRequest
0 голосов
/ 22 февраля 2019

Я готовлю структуру данных проекта ( сначала код ) в ASP .NET Core 2 приложении с помощью Entity Framework .С этими конкретными отношениями у меня нет опыта: пользователь должен иметь возможность выбирать заболевания с помощью флажков, и у нас есть похожие варианты: тип рака, диетическое питание и т. Д.

У меня есть более двух таблиц, подобных темна рисунке, который будет ссылаться из таблицы UserKitProperties .Эта таблица должна работать как таблица соединителей, связывая пользовательский объект с другими объектами.

userid1 | cancertypeid1
userid2 | dietaryid1
userid1 | cancertypeid2
userid3 | dietaryid1

enter image description here

Как это должно быть указано в коде,поддержать эти отношения?Я думал о создании базового класса и, возможно, сослаться на этот идентификатор.И это класс разъема ..

public class PatientProperties : EntityModel
    {
        [Key]
        public long ID { get; set; }

        public long PatientID { get; set; }

        [ForeignKey("PatientID")]
        public Patient Patients { get; set; }

        // this should be used for cancer type, dietary, etc..
        public long PropertyID { get; set; }

        /* Instead of using two classes' ids, maybe call the base class' id
        [ForeignKey("PropertyID")]
        public CancerType CancerTypes { get; set; }

        [ForeignKey("PropertyID")]
        public Dietary Dietaries { get; set; } */
    }

Заранее спасибо за ваши предложения!:)

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Вместо того, чтобы сначала думать о компоновке базы данных, вы должны подумать о том, как бы вы представляли эти отношения в коде.В конце концов, вы используете подход, основанный на коде.

По сути, вы можете выбрать один из двух вариантов: либо у пациента есть несколько свойств, по одному для каждого типа свойства, либо существует только одна коллекция для всех свойств.:

public class Patient
{
    // …

    // option 1
    public CancerType CancerType { get; set; }
    public Dietary Dietary { get; set; }
    public OtherProperty OtherProperty { get; set; }

    // option 2
    public IList<PatientProperty> Properties { get; set; }
}

Оба эти варианта имеют свои преимущества и недостатки.Хотя опция 1 является очень явной и предусматривает одно значение для каждого типа, она также требует наличия свойства (класса) для каждого свойства (пациента).Поэтому, если вы позже расширите свою модель, вам придется скорректировать модель своего пациента.

Option 1

Преимущество варианта 2 заключается в том, что он может просто собрать все.Таким образом, вы можете просто добавить свойства своему пациенту, не изменяя модель позже, если вы введете новые свойства.Кроме того, он также будет напрямую поддерживать несколько вариантов выбора для одного вида.С другой стороны, он ничего не проверяет сам по себе, поэтому вам нужна бизнес-логика для фактического применения ваших правил.

Option 2


Перемещение в базу данных, для варианта 2вам, очевидно, нужна таблица ссылок, так как сейчас это отношение «многие ко многим».Поскольку у вас есть только ссылка на базовый тип PatientProperty, но вы действительно хотите поговорить о конкретном типе, вам понадобится какой-то дискриминатор .Дискриминаторы - это, по сути, просто нотация для дополнительного хранения вида объекта в базе данных.

При хранении данных с наследованием обычно делается «таблица на иерархию».Это означает, что все типы в иерархии базового типа PatientProperty будут использовать одну и ту же таблицу.Столбец дискриминатора используется для указания типа, а дополнительные свойства, которые могут иметь некоторые типы свойств, реализованы со столбцами, допускающими обнуляемость.Эта установка работает из коробки с Entity Framework и описана в этой главе в документации .

Другой подход, «таблица на тип», не поддерживается в EF Core,поэтому, если вы хотите следовать этому, вам придется реализовать это самостоятельно.Но в вашем случае, когда типы свойств в основном очень похожи, я бы даже поспорил с этим и фактически оставил бы их в одной таблице.

Для варианта 1, если у вас есть только одно свойство каждогоВид назначен пациенту, все немного проще.Так как у вас там нет многих ко многим, вам на самом деле не нужна таблица ссылок.Вам просто нужно сохранить идентификатор для каждого связанного типа свойства в модели пациента, как показано в приведенном выше UML.При этом вы также можете сохранить типы свойств как отдельные типы, которые не разделяют одну таблицу в базе данных.

0 голосов
/ 22 февраля 2019

Должно работать следующее:

public class Property 
{
    public long PropertyId { get; set; }
}

public class CancerType : Property 
{ 
    // Your code
}

public class Dietary : Property 
{   
    // Your code
}

public class PatientProperties : EntityModel
{
    [Key]
    public long ID { get; set; }

    public long PatientID { get; set; }

    [ForeignKey("PatientID")]
    public Patient Patients { get; set; }

    public long PropertyID { get; set; }

    [ForeignKey("PropertyID")]
    public Property Property { get; set; }
}

Но, как упоминает MS doc , для настройки такого наследования будет использоваться специальный столбец Discriminator в базовом классе.таблица, чтобы представить, какой конкретный тип хранится в строке.

Лично я бы использовал вместо этого пустые поля, чтобы не усложнять ситуацию.Однако это не означает, что PatientProperties имеет только одно свойство, что является существенным минусом:

public class PatientProperties : EntityModel
{
    [Key]
    public long ID { get; set; }

    public long PatientID { get; set; }

    [ForeignKey("PatientID")]
    public Patient Patients { get; set; }

    public long? CancerTypeID { get; set; }
    [ForeignKey("CancerTypeID")]
    public CancerType CancerType { get; set; }

    public long? DietaryID { get; set; }
    [ForeignKey("DietaryID")]
    public Dietary Dietary { get; set; }
}
...