简体   繁体   中英

Entity Framework Core: How to perform a Join on `IQueryable` by selecting only the latest created records?

I am refactoring a code in production which create duplicates:

private IQueryable<CashoutModel> GetCashoutModels() =>
    from cashout in _context.Cashouts
    join audit in _context.Audits
        on cashout.Id.ToString() equals audit.EntityId
        into cashoutModel
    from audit in cashoutModel.DefaultIfEmpty()
    orderby cashout.CreatedOn descending
    select new CashoutModel
    {
        Id = cashout.Id,
        Amount = cashout.Amount,
        Comment = cashout.Comment,
        CreatedOn = cashout.CreatedOn,
        RecipientAccountId = cashout.RecipientAccountId,
        RecipientAccountName = cashout.RecipientAccountName,
        State = cashout.State,
        Reason = cashout.Reason,
        CreatedBy = audit == null 
            ? null 
            : audit.Name
    };

The _context.Audits actually records (use-triggered) changes that happen for certain records in _context.Cashout .

I am looking for a clean way to fix the current behavior of the join by selecting only (for a given EntityId ) the latest audit record.

The code you currently have is essentially doing a LEFT OUTER JOIN which gets all the Cashouts records and the corresponding audit record.

Assuming you have a timestamp column (say CreatedOn ) in the Audits table which captures when that audit record was created, you could use a GROUP JOIN here like so -

private IQueryable<CashoutModel> GetCashoutModels() =>
_context.Cashouts.GroupJoin(_context.Audits,
                            c => c.Id.ToString(),
                            a => a.EntityId,
                            (cashout, audit) => new CashoutModel
                                {
                                    Id = cashout.Id,
                                    Amount = cashout.Amount,
                                    Comment = cashout.Comment,
                                    CreatedOn = cashout.CreatedOn,
                                    RecipientAccountId = cashout.RecipientAccountId,
                                    RecipientAccountName = cashout.RecipientAccountName,
                                    State = cashout.State,
                                    Reason = cashout.Reason,
                                    CreatedBy = audit.OrderByDescending(x => x.CreatedOn)
                                                    .Select(y => y.Name)
                                                    .FirstOrDefault()
                                }).AsQueryable();

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