C# Linq EF-如何通过优化查询从数据库中收集特定客户的所有帐户、卡、贷款等?

C# Linq EF-如何通过优化查询从数据库中收集特定客户的所有帐户、卡、贷款等?,c#,asp.net-mvc,entity-framework,linq,C#,Asp.net Mvc,Entity Framework,Linq,我试图从我的数据库中收集特定客户的所有信息,但我不确定如何在优化查询中收集所有信息,而不必多次查询数据库 我有以下表格: 我想要的是将1个客户与提供的CustomerId匹配。然后收集所有与该账户相关的卡、账户、贷款和永久订单 我成功地做到了这一点,但对我的_上下文使用了几个查询。我想学习如何在连接多个表时进行优化查询 对于Linq更有经验的人能否提供一个查询示例,以收集与CustomerId为“1”的客户相关的所有卡、账户、贷款和永久订单 如果能得到一些提示和帮助,我将非常感激,知道如何进行优

我试图从我的数据库中收集特定客户的所有信息,但我不确定如何在优化查询中收集所有信息,而不必多次查询数据库

我有以下表格:

我想要的是将1个客户与提供的CustomerId匹配。然后收集所有与该账户相关的卡、账户、贷款和永久订单

我成功地做到了这一点,但对我的_上下文使用了几个查询。我想学习如何在连接多个表时进行优化查询

对于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();
下面是我试图用数据填充的viewmodel:

 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>();

}
公共类GetCustomerDetailsViewmodel
{
公共客户客户{get;set;}
公共列表帐户{get;set;}=new List();
公共十进制总余额{get;set;}
公共列表卡{get;set;}=new List();
公共列表{get;set;}=new List();
公共列表贷款{get;set;}=new List();
}
客户有一个处置列表,即客户-账户和卡之间的链接表

**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; }
**客户**
PK客户ID
公共虚拟ICollection配置{get;set;}
**卡片**:
PK public int CardId{get;set;}
FK public int DispositionId{get;set;}
公共虚拟处置{get;set;}
**处置**:
PK public int DispositionId{get;set;}
FK public int CustomerId{get;set;}
public int AccountId{get;set;}
公共虚拟帐户{get;set;}
公共虚拟客户客户{get;set;}
公共虚拟ICollection卡{get;set;}
**账户**:
PK public int AccountId{get;set;}
公共虚拟ICollection配置{get;set;}
公共虚拟ICollection贷款{get;set;}
公共虚拟ICollection PermenentOrder{get;set;}
公共虚拟ICollection事务{get;set;}
**贷款**
PK public int LoanId{get;set;}
公共虚拟帐户{get;set;}
**永久秩序**
PK public int OrderId{get;set;}
FK公共int帐户ID{get;set;}
公共虚拟帐户{get;set;}

我想你可以用这个:

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);

最简单的查询将是单独查询,而不是塞进单个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();
        }

dbSet.Include(…)
即使使用System.Data.Entity添加
,也可以使用表达式支持将您的viewmodel代码作为代码而不是图像添加到问题中。我尝试了以下操作:“var test=wait\u context.Dispositions.Include(d=>d.Account)。然后Include(d=>d.Loans)。Include(d=>d.Account)。然后Include(d=>d.PermenentOrder)。Include(d=>d.Cards).Where(c=>c.CustomerId==request.CustomerId).Distinct().FirstOrDefaultAsync();'不幸的是,我不知道如何获得多个帐户,因为我的查询只获得一个帐户。有什么见解吗?感谢者有一系列的气质,不幸的是他们没有卡片列表。配置是它们之间的链接表。有什么建议吗?我以前没有使用过include,我现在正在努力阅读:-)编辑:我编辑了我的帖子并添加了信息我认为你可以使用
include
然后include
,但是把模型放在你的问题中,我可以更好地帮助你。为了进一步优化,您可以只选择查询所需的数据,而不是返回所有数据。i、 e:
.Select(x=>newviewmodel{Blah=x.Blah,Children=x.Blah.Children}
而不是像现在使用
.SingleOrDefault
那样返回整个实体。对于包含许多列的大型表,这将产生很大的不同。这本质上是sql中
select*from table
select col1,col2 from table
之间的区别,这是处理此问题的最干净的方法假设就是这个答案,它可以被认为是正确的答案,但如果你坚持不在代码中使用include,那么你可以在实体之间使用join,你应该像这样将每个select转换为viewmodel:
selectnewparentviewmodel{Id=p.Id,Children=p.Children.select(c=>newchildviewmodel{Id=c.Id,Toys=c.Toys.Select(t=>newtoyviewmodel{…}).ToList()}.ToList()}
谢谢你的回复垫!我试用了你的代码,但它没有加载帐户、卡或永久订单。只有客户被加载。你知道为什么吗?我真的很喜欢你的方法,因为它非常简短直接。也许这与延迟/急切加载有关?谢谢启用了?嗨,垫,延迟加载不是enabled。我的老师警告我不要启用它以避免加载不必要的数据。你建议怎么做?你应该启用延迟加载,但不应该在视图模型属性中直接公开实体类型。延迟加载不会加载不必要的数据,它按设计只加载必要的数据。使用具有必要属性的客户视图模型s、 然后将customer属性更改为该模型类。这样,意外加载不必要的数据可能会