简体   繁体   中英

In EF Core, should I use database query to join one to many table or use manual joining by efcore in the c#?

I have three tables in EF Core code-first database which have a one-to-many-to-one relationship:

public class Operator
{
    [Key]
    public string Username { get; set; }
    public string PhoneNumber { get; set; }

    public List<Ticket> Tickets { get; set; }
}

public class Ticket
{
    public int TicketId { get; set; }
    public DateTime Date { get; set; }
    public int LotNumber { get; set; }
    public enum TicketStatus { get; set; }

    // navigation properties
    public Specification Specification { get; set; }
    
    // foreign keys
    public string OperatorUsername { get; set; }
    public int SpecificationId { get; set; }
}

public class Specification
{
    public int SpecificationId { get; set; }
    public int Wages { get; set; }
    public string ColorName { get; set; }
    public string SizeName { get; set; }
    public string Description { get; set; }
}

As you can see, one operators can have many tickets, also one specification can have many tickets.

However in one specification we can have hundreds to thousands of tickets. The problem is right now I want to fetch data using EF Core starting from operators to check for all the the tickets that the operator has attended and what is the specification for the tickets.

So this is inside my controller right now.

public Task<Operator> GetOperatorWithTickets(Username)
{
    return await context.Operator
                        .Include(x => x.Tickets)
                        .ThenInclude(y => y.Specification)
                        .FirstOrDefaultAsync(c => c.Username == Username);
}

However after inspecting the query that EF Core generated, I find that EF Core uses join query to get all three tables together, and I think it might not be very efficient to keep scanning table Specification for every single tickets in join query.

I am considering this method using FindAsync to reuse existing tracked Specification entities

public Task<Operator> GetOperatorWithTickets(Username)
{
    Operator Operator await context.Operator
                                   .Include(x => x.Tickets)
                                   .FirstOrDefaultAsync(c => c.Username == Username);
 
    foreach (Ticket ticket in Operator.Tickets)
    {
         ticket.Specification = await context.ticket.FindAsync(ticket.SpecificationId);
    }

    return Operator;
}

I believe second method can reduce database overhead because database scan for table Specification will only be performed when the entity Specification is not yet retrieve for all previous any tickets, else the existing entities will be used again and again for hundreds or even thousands of tickets that share same specification.

I am still a novice and not sure about all the caching that database might performs to reduce the overhead in first method, so in my view second method should outperforms the first method. What is your view on this? Should I stick with the first methods or migrate to second methods?

After reading some comments, I believe database catching will automatically improve the data retrieval using first method, thus even though same data will be retrieve again and again, but database catching will help to reduce the overhead and significantly improve database speed on join methods.

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