我有这样的查询
public IEnumerable<ContractInquiry> ContractInquiry(Guid itemSoldID)
{
IEnumerable<ContractInquiry> result;
using (var context = new ContractDbContext(_ctxOptions))
{
var qry = from con in context.Contracts
join product in context.ContractProducts on con.ID equals product.ContractID
join service in context.ServiceDetails on con.ID equals service.ContractID into tmpService
from service in tmpService.DefaultIfEmpty()
where product.ItemSoldID == itemSoldID
&& product.ProductStatus != ProductStatus.Deleted.ToString()
&& con.Status != Status.Deleted.ToString()
select new ContractInquiry
{
ServiceID = con.ID,
ServiceType = con.ServiceType,
ServiceDate = service.ServiceDate,
ServiceNumber = service.ServiceNumber,
ServiceManager = con.Contacts.Where(q => q.Role.Contains(ContractRole.ServiceManager.ToString()))
.OrderBy(o => o.ID).FirstOrDefault()
};
result = qry.ToList();
}
return result;
}
此查询工作正常。但是,当我们升级到.NET Core 3.1.5和Entity Framework Core 3.1.5时,它开始引发客户端评估错误:
”无法翻译。要么以可以翻译的形式重写查询,要么通过插入对AsEnumerable(),AsAsyncEnumerable(),ToList()或ToListAsync()的调用来显式切换到客户端评估。 “
所以我不得不从查询中删除以下行:
ServiceManager = con.Contacts.Where(q => q.Role.Contains(ContractRole.ServiceManager.ToString()))
.OrderBy(o => o.ID).FirstOrDefault()
因此重新编写如下查询:
public IEnumerable<ContractInquiry> ContractInquiry(Guid itemSoldID)
{
List<ContractInquiry> result;
using (var context = new ContractDbContext(_ctxOptions))
{
var result = (from con in context.Contracts
join product in context.ContractProducts on con.ID equals product.ContractID
join service in context.ServiceDetails on con.ID equals service.ContractID into tmpService
from service in tmpService.DefaultIfEmpty()
where product.ItemSoldID == itemSoldID
&& product.ProductStatus != ProductStatus.Deleted.ToString()
&& con.Status != Status.Deleted.ToString()
select new ContractInquiry
{
ServiceID = con.ID,
ServiceType = con.ServiceType,
ServiceDate = service.ServiceDate,
ServiceNumber = service.ServiceNumber,
Contacts = con.Contacts
}).ToList();
}
result.ForEach(con => con.Contacts.Where(q => q.Role.Contains(ContractRole.ServiceManager.ToString()))
.OrderBy(o => o.ID).FirstOrDefault();
return result;
}
这里
con.Contacts
是 Contract.cs 类
中的表集合我在 ContractInquiry.cs 类中添加了这样的属性:
[JsonIgnore]
public IEnumerable<Contact> Contacts { set; get; }
这也很好。
问题: 这样做会很好,但是在运行时,表集合“ con.Contacts”将在内存中对吗?如果表是一个巨大的集合,那会影响查询的性能吗?那么有没有解决的办法,而不是使用内存表?如何在我的第一个查询中的select子句中取出“ ServiceManager = ..”?
更新:有人可以回答我的问题吗?
答案 0 :(得分:0)
回答您的问题:
这是为什么:
EF Core仅在需要时加载相关数据。例如,调用.ToList()
时,您有1000个这些ContractInquiry记录。这些记录中的每一个包含十个联系人。然后,EF Core将仅加载1000 * 10个触点。由于引用(如果这些引用中有任何重叠),它们将共享内存位置,并且仅保存对其的引用。
您可以进行一些更改以使其更快:
.ToList()
更改为.AsEnumerable()
。之所以可以这样做,是因为您仅对该列表进行一次迭代,因此可以使用.AsEnumerable()
保存整个迭代。 (要创建列表,程序必须对其进行迭代,然后再次对其进行迭代)。另外,您返回的是IEnumerable,因此创建列表是没有意义的(如果您要对其进行一次迭代(在这种情况下就是这种情况)),除非您稍后将其回退(我不建议这样做)。.AsNoTracking()
。我不知道如何通过这种查询来实现相同的目的(我仅使用Linq)。这将节省大量时间,因为EF Core无需创建跟踪(也将节省内存)。如果您将查询更改为Linq查询,我们将很高兴为您提供帮助并对其进行优化。