简体   繁体   中英

EF Core query and projection to dto doesn't fill the property

How to write EF Core query to fill the properties in certain order?

public record PersonDto : BaseDto //Id is Guid
{
    public string Firstname { get; init; }
    public string Lastname { get; init; }

    public DateOnly Birthday { get; init; }

    public IReadOnlyCollection<Guid> AddressesIds { get; init; }

    public Guid? MainAddressId { get; init; }
}

internal class Person : SoftDeletableEntity //Id is Guid
{
    public Person()
    {
        Addresses = new HashSet<Address>();
        Emails = new HashSet<Email>();
        PhoneNumbers = new HashSet<PhoneNumber>();
    }

    public string Firstname { get; set; }
    public string Lastname { get; set; }

    public DateOnly Birthday { get; set; }

    public ICollection<Address> Addresses { get; set; }

    public Guid? MainAddressId => MainAddress?.Id;

    public Address? MainAddress => Addresses.Where(adr => adr.IsPrimary).FirstOrDefault();
}

internal sealed partial class Context : DbContext
{
    public DbSet<Person> People => Set<Person>();
}

var context = new Context();
var peopleQuery = context.People
    .Skip(10)
    .Take(10)
    .Select(p=> new PersonDto(){
    AddressesIds = new HashSet<Guid>(p.Addresses.Select(a => a.Id).Where(a => a.IsPrimary),
    MainAddressId = p.MainAddressId,
    //bla bla 
};
var peopleResult = people.ToList();

At the end of this fragment, peopleResult has all the addresses ids have been loaded, but the MainAddressId of the dto is null.

When I debug the code, MainAddressId is called before populate the list of Addresses , how I change this, or how is this supposed to be done if I'm doing it wrong.

Thanks in advance.

I Think the problem is that calculated properties in your entity. I had a similar problem a few months ago. I just removed that properties from my Entity an put it in my DTOs.

Do you really need MainAddressId and MainAddress properties of the Person . As I understand you have these in the Address model? You can just do the select like this:

var peopleQuery = context.People
    .Skip(10)
    .Take(10)
    .Select(p=> new PersonDto(){
    AddressesIds = new HashSet<Guid>(p.Addresses.Select(a=> a.Id),
    MainAddressId = p.Addresses.FirstOrDefault(a=> a.IsPrimary),
};
var peopleResult = people.ToList();

You need only the Addresses, then you can easily filter which is the main one, and assign it to the DTO's property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM