Найдите эквивалентный вложенный объект внутри базы данных с помощью Entity Framework 6

avatar
Sassa
7 апреля 2018 в 23:28
457
2
1

У меня есть таблицы Patient и Institution, к которым я обращаюсь с помощью EF6

public class Patient
{
    [Key]
    public int PatientId { get; set; }
    public string PatientName { get; set; }
    public virtual Institution Institution { get; set; }
}

public class Institution
{
    [Key]
    public int InstitutionId { get; set; }
    public string InstitutionName { get; set; }
    public virtual ICollection<Patient> Patients { get; set; }
}

Теперь, допустим, я создаю объект Patient вручную, что-то вроде этого:

var newPatient = new Patient {
    PatientName = "Edward",
    Institution = new Institution {
        InstitutionName = "SomeInstitution"
    },
};

Теперь я хочу проверить, есть ли у меня уже пациент по имени "Эдвард" в учреждении "SomeInstitution".

Мой вопрос в том, как это сделать, сейчас у меня есть такой запрос:

public static Patient QueryFromAllProperties(MyDbContextcontext, Patient patient)
{
    return context.Patients
            .Where(p => p.PatientName == patient.PatientName)
            .SingleOrDefault();
}

var patient = QueryFromAllProperties(context, newPatient);

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

Обратите внимание, я думаю, что могу просто изменить where на:

.Where(p => p.PatientName == patient.PatientName
            && p.Institution.InstitutionName == patient.Institution.InstitutionName)

Это будет работать более или менее, но это не чисто (это всего лишь простой пример, в моем коде гораздо больше вложенных сущностей с большим количеством свойств, которые мне нужно проверить), очень стандартно и сломается, если Institution равно null.

PS: обратите внимание, что я игнорирую InstitutionId, поскольку я не хочу сравнивать ключи (я хочу найти ключ в базе данных, который настраивает именно эти значения объекта), и я игнорирую ICollection<Patient> Patients, поскольку это просто list для настройки отношения «многие к одному».

Итак, есть ли другой лучший способ сделать это?

Кроме того, я хотел бы знать, как справиться с этим в случае отношения "многие ко многим", поэтому в этом случае мы можем переписать таблицы как:

public class Patient
{
    [Key]
    public int PatientId { get; set; }
    public string PatientName { get; set; }
    public virtual ICollection<Institution> Institutions { get; set; }
}

public class Institution
{
    [Key]
    public int InstitutionId { get; set; }
    public string InstitutionName { get; set; }
    public virtual ICollection<Patient> Patients { get; set; }
}

И в этом случае из части Institutions я хотел бы проверить, будет ли Patient внутри базы данных содержать все учреждения, которые в настоящее время есть у объекта (не имеет значения, если в базе данных Patient больше Institutions, чем тот, который я создал.

Источник

Ответы (2)

avatar
Kind Contributor
7 апреля 2018 в 23:51
1

В то время как в C# нужно проверять нулевой объект, в Entity framework и Sql этого не происходит. Ваш запрос преобразуется в sql и выполняется на сервере базы данных с внутренним соединением.

Для кардинальности "многие ко многим" либо добавьте связующую таблицу вручную, либо посмотрите, как сделать "свободное сопоставление" с помощью EF.

И не беспокойтесь о попытках найти более короткие представления или "более чистые" строки кода. Расставьте приоритеты для того, что увидит пользователь, и общую организацию вашего кода для удобства сопровождения: классы, функции.

avatar
dumbchemistry
7 апреля 2018 в 23:51
2

Использование функции Any может немного упростить задачу. Any — это функция, которая вернет true, если в коллекции есть какой-либо элемент, соответствующий заданному вами условию.

var exists = context
    .Patients
    .Any(p => p.PatientName == patient.PatientName && 
         p.Institution.InstitutionName == patient.Institution.InstitutionName);

Это вернет bool, говорящий вам, существует ли он уже вместо объекта Patient.