问题描述
其中之一是数据库优先-由旧版企业应用程序管理的数据库,我对更改数据库结构没有完全控制权。
第二个是代码优先的代码,我可以完全控制代码优先的数据库进行更改。
安全策略使我无法在代码优先的DB中创建将两个数据库服务器中的表联接起来的视图,这可能是一种根据我在SO帖子中看到的方法进行改进的方法。
代码优先表中的数据和结构被设计为能够连接到非代码优先数据库,就像它们都在一个数据库中一样。
// Set up EF tables
var person = await _context1.Person.ToListAsync();
var labor = await _context1.Labor.ToListAsync();
var laborCraftRate = await context1.LaborCraftRate.ToListAsync();
var webUsers = await context2.WebUsers.ToListAsync();
var workOrders = await _context1.Workorder
.Where(r => r.Status == "LAPPR" || r.Status == "APPR" || r.Status == "REC")
.ToListAsync();
var specialRequests = await _context1.SwSpecialRequest
.Where(r => r.Requestdate > DateTime.Now)
.ToListAsync();
var distributionListQuery = (
from l in labor
from p in person.Where(p => p.Personid == l.Laborcode).DefaultIfEmpty()
from wu in webUsers.Where(wu => wu.Laborcode == l.Laborcode).DefaultIfEmpty()
from lcr in laborCraftRate.Where(lcr => lcr.Laborcode == l.Laborcode).DefaultIfEmpty()
select new
{
Laborcode = l.Laborcode,displayname = p.displayname,Craft = lcr.Craft,Crew = l.Crewid,Active = wu.Active,Admin = wu.FrIsAdmin,FrdistLocation = wu.FrdistLocation,}).Where(r => r.Active == "Y" && (r.FrdistLocation == "IPC" || r.FrdistLocation == "IPC2" || r.FrdistLocation == "both"))
.OrderBy(r => r.Craft)
.ThenBy(r => r.displayname);
// Build a subquery for the next query to use
var ptoSubQuery =
from webUser in webUsers
join workOrder in workOrders on webUser.Laborcode equals workOrder.Wolablnk
join specialRequest in specialRequests on workOrder.Wonum equals specialRequest.Wonum
select new
{
workOrder.Wonum,Laborcode = workOrder.Wolablnk,specialRequest.Requestdate
};
// Build the PTO query to join with the distribution list
var ptoQuery =
from a in ptoSubQuery
group a by a.Wonum into g
select new
{
Wonum = g.Key,StartDate = g.Min(x => x.Requestdate),EndDate = g.Max(x => x.Requestdate),Laborcode = g.Min(x => x.Laborcode)
};
// Join the distribution list and the object list to return
// list items with PTO information
var joinedQuery = from dl in distributionListQuery
join fl in ptoQuery on dl.Laborcode equals fl.Laborcode
select new
{
dl.Laborcode,dl.displayname,dl.Craft,dl.Crew,dl.Active,dl.Admin,dl.FrdistLocation,fl.StartDate,fl.EndDate
};
// There are multiple records that result from the join,// strip out all but the first instance of PTO for all users
var distributionList = joinedQuery.GroupBy(r => r.Laborcode)
.Select(r => r.FirstOrDefault()).OrderByDescending(r => r.Laborcode).ToList();
同样,这可以在合理但显然不是最佳的时间范围内恢复数据,而我可以在需要此时间的UI中通过在需要时预加载数据来进行恢复。不是最好的,但是有效。
如果我在另一个SO帖子中告诉我应该将变量声明更改为不异步,这将变成跨数据库查询,并且netcore拒绝:
// Set up EF tables
var person = _context1.Person;
var labor = _context1.Labor;
var laborCraftRate = context1.LaborCraftRate;
var webUsers = context2.WebUsers;
var workOrders = _context1.Workorder
.Where(r => r.Status == "LAPPR" || r.Status == "APPR" || r.Status == "REC");
var specialRequests = _context1.SwSpecialRequest
.Where(r => r.Requestdate > DateTime.Now);
添加ToListAsync()是使我需要工作的联接功能的原因。
问-任何人都可以详细说明我正在做的事情的弊端和问题吗?
感谢您帮助我理解!
解决方法
不是说ToList()
“不起作用”。问题在于它实现了查询(我认为这是正确的词),并向客户端返回了可能大于预期的数据量。任何进一步的LINQ操作都在客户端进行。这会增加数据库和网络上的负载。在您的情况下,起作用是因为您将所有这些数据都带到了客户端。到那时,不再需要跨数据库查询了。
这是从.NET Core 2.x过渡到3.x时经常遇到的问题。如果无法在服务器端执行操作,则.NET Core 2.x会静默插入类似ToList()
之类的内容。 (嗯,不是完全默默无闻。我认为它已记录在某处。但是许多开发人员并未意识到这一点。)3.x停止这样做并会给您一个错误。当人们尝试升级到3.x时,他们经常发现很难将查询转换为可以在服务器端运行的内容。人们拒绝使用明确的ToList()
,因为它们的性能很高。但是请记住,这就是它一直在做的事情。如果以前没有性能问题,那么现在就没有问题了。而且至少现在您知道它的实际功能,并在需要时可以对其进行修复。