Linq EF - Как собрать все учетные записи, карты, кредиты и т. Д. Конкретного клиента из базы данных с помощью оптимизированного запроса? - PullRequest
4 голосов
/ 14 мая 2019

Я пытаюсь собрать всю информацию о конкретном клиенте из моей базы данных, но я не уверен, как собрать всю информацию в оптимизированном запросе, не запрашивая базу данных несколько раз.

У меня есть следующие таблицы: https://i.imgur.com/o9PRrF1.png

Я хочу сопоставить 1 клиента с предоставленным CustomerId.Затем соберите все карты, счета, кредиты и постоянные заказы, связанные с этим счетом.

Мне удалось это сделать, но я использовал несколько запросов к своему _context.Я хочу узнать, как выполнять оптимизированные запросы при объединении нескольких таблиц.

Может ли кто-нибудь с большим опытом работы с Linq предоставить пример запроса для сбора всех карточек, счетов, ссуд и постоянных клиентов, связанных с клиентом с помощью CustomerIdиз "1"?

Я был бы очень признателен, чтобы получить несколько советов и помочь с этим, знание, как выполнять оптимизированные запросы, является очень важным навыком.Большое спасибо!: -)

Пример того, что я попробовал сам:

model.Customer = await _context.Customers.SingleOrDefaultAsync(c => c.CustomerId == request.CustomerId);

        model.Accounts = await (from acc in _context.Accounts
                                join disp in _context.Dispositions on acc.AccountId equals disp.AccountId
                                where disp.CustomerId == request.CustomerId
                                select acc).ToListAsync();

        model.Cards = await (from card in _context.Cards
                             join disp in _context.Dispositions on card.DispositionId equals disp.DispositionId
                             where disp.CustomerId == request.CustomerId
                             select card).ToListAsync();

Вот моя модель представления, которую я пытаюсь заполнить данными:

 public class GetCustomerDetailsViewmodel
{
    public Customer Customer { get; set; }
    public List<Account> Accounts { get; set; } = new List<Account>();
    public decimal TotalBalance { get; set; }
    public List<Card> Cards { get; set; } = new List<Card>();
    public List<PermenentOrder> PermantentOrders { get; set; } = new List<PermenentOrder>();
    public List<Loan> Loans { get; set; } = new List<Loan>();

}

Клиенты имеют список диспозиций, таблицу связей между клиентами - счетами и картами.

**Customers**
PK CustomerId
public virtual ICollection<Disposition> Dispositions { get; set; }

 **Cards**:
PK public int CardId { get; set; }
FK public int DispositionId { get; set; }
public virtual Disposition Disposition { get; set; }

**Dispositions**:
PK public int DispositionId { get; set; }
FK public int CustomerId { get; set; }
   public int AccountId { get; set; }
public virtual Account Account { get; set; }
public virtual Customer Customer { get; set; }
public virtual ICollection<Card> Cards { get; set; }

**Accounts**:
PK public int AccountId { get; set; }
public virtual ICollection<Disposition> Dispositions { get; set; }
public virtual ICollection<Loan> Loans { get; set; }
public virtual ICollection<PermenentOrder> PermenentOrder { get; set; }
public virtual ICollection<Transaction> Transactions { get; set; }

**Loans**
PK public int LoanId { get; set; }
public virtual Account Account { get; set; }

**PermenentOrder**
PK public int OrderId { get; set; }
FK public int AccountId { get; set; }
public virtual Account Account { get; set; }

Ответы [ 2 ]

2 голосов
/ 14 мая 2019

Я думаю, вы можете использовать это:

model.Customer = await _context.Customers
    .Include(x => x.Dispositions)
    .ThenInclude(x => x.Cards)
    // and other Entities you need, use Include or if entities are in Accounts
    // or Cards can use ThenInclude
    .SingleOrDefaultAsync(c => c.CustomerId == request.CustomerId);
1 голос
/ 14 мая 2019

Самый простой запрос будет заключаться в том, чтобы запрашивать отдельно, а не втиснуть в один оператор linq, поскольку оператор растет, linq становится все более и более неэффективным.

С отложенной загрузкой,

Вы можете сделать что-то простое, как,

var model = new GetCustomerDetailsViewmodel();
model.Customer = context.Customers.SingleOrDefault(c => c.CustomerId == id);
if (model.Customer != null)
{
     model.Accounts = model.Customer.Dispositions.Select(x => x.Account).ToList();
     model.Cards = model.Customer.Dispositions.SelectMany(x => x.Cards).ToList();
     model.PermantentOrders = model.Accounts.SelectMany(x => x.PermenentOrder).ToList();
}

Без отложенной загрузки,

Вам нужно загрузить все в одном запросе, но это может быть неэффективный запрос. Linq - это не эффективность, а удобство и простота написания.

var customerProfile = context.Customers.Where(x => x.CustomerId == id).Select(x => new
        {
            Customer = x,
            Accounts = x.Dispositions.Select(d => d.Account),
            Cards = x.Dispositions.SelectMany(d => d.Cards).ToList(),
            PermanentOrders = x.Dispositions.SelectMany(d => d.Account.PermenentOrder),
        }).FirstOrDefault();

        if (customerProfile != null)
        {
            var model = new GetCustomerDetailsViewmodel();
            model.Customer = customerProfile.Customer;
            model.Accounts = customerProfile.Accounts.ToList();
            model.Cards = customerProfile.Cards.ToList();
            model.PermantentOrders = customerProfile.PermanentOrders.ToList();
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...