Как использовать собственные типы в LINQ?

Используя собственные типы в Entity Framework Core 2.2.6, как мне написать запрос LINQ, который действует на равенство принадлежащего типа?

Я создаю приложение, использующее концепции DDD, такие как Entities и Value Objects. Например. Person имеет PersonName. PersonName - это объект значения, который предоставляет методы и операторы равенства.

public sealed class PersonConfiguration : IEntityTypeConfiguration<Person>
{
    public void Configure(EntityTypeBuilder<Person> entity)
    {
        entity.HasKey(its => its.Id);
        entity.OwnsOne(its => its.Name);
    }
}

public class Person
{
    private Person() { }

    public Person(Guid id, PersonName name) => (Id, Name) = (id, name);

    public Guid Id { get; private set; }

    public PersonName Name { get; private set; }
}

public class PersonName
{
    private PersonName() { }

    public PersonName(string firstName, string lastName) => (FirstName, LastName) = (firstName, lastName);

    public string FirstName { get; private set; }

    public string LastName {get; private set; }

    protected static bool EqualOperator(PersonName left, PersonName right)
    {
        // Omitted: equality check
    }

    protected static bool NotEqualOperator(PersonName left, PersonName right)
    {
        // Omitted: inequality check
    }

    public override bool Equals(object? obj)
    {
        // Omitted: equality check
    }

    public override int GetHashCode()
    {
        // Omitted: hashcode algorithm
    }
}

Например, мне нужно найти всех людей в моей базе данных с одинаковыми именем и фамилией.

Что я пробовал:

private readonly PersonContext Db = new PersonContext();
public IEnumerable<Person> FindByName(PersonName name)
{
    return from person in Db.People
           where person.Name == name
           select person;
}
---
var johnDoes = FindByName(new PersonName("John", "Doe"));

Это компилируется и запускается, но возвращает пустую коллекцию.


person Steven Liekens    schedule 24.02.2020    source источник


Ответы (1)


Попробуйте отфильтровать по отдельным полям:

public IEnumerable<Person> FindByName(PersonName name)
{
return from person in Db.People
       where person.Name.FirstName == name.FirstName && person.Name.LastName == name.LastName
       select person;
}
person Vladimir    schedule 24.02.2020
comment
Спасибо, не стоит ли мне беспокоиться о нарушении инкапсуляции моих объектов значений? По сути, это дублирует проверки равенства в коде доступа к данным. - person Steven Liekens; 24.02.2020
comment
При изменении данных требуется инкапсуляция. Нет необходимости в инкапсуляции, если данные не изменены, как в этом примере. - person Vladimir; 25.02.2020