最近,当我在我们的项目中发现问题时,我一直在重构一些笨拙而不工作的LINQ查询。这是一个让我陷入困境的人。我必须承认,我是一个使用实体框架弹入C#的Android开发人员,所以我并不真正了解这里发生的事情。不过,这些查询对我而言几乎相同(在此处撒上子查询,在此处撒上新的联接)。第一个方法将返回无错误:
public virtual IQueryable<ScratchGameDetailsModel> GetScratchGameDetails(string reconGUID)
{
var lotteryReconHeader = _lotteryReconHeaderRepository.GetAll().AsEnumerable(); // Changed on Nov 7,2017
var lotteryReconDetails = _lotteryReconDetailRepository.GetAll().Where(s => s.ReconGUID == reconGUID).AsEnumerable();
var lotteryGames = _lotteryGameRepository.GetAll().AsEnumerable();
var lotteryActivations = _lotteryActivationRepository.GetAll().AsEnumerable();
var response = (from ltrd in lotteryReconDetails
join lg in lotteryGames on ltrd.GameGUID equals lg.GameGUID
join la in lotteryActivations on lg.GameGUID equals la.GameGUID into LotteryActivations_join
from la in LotteryActivations_join.DefaultIfEmpty()
join ltrh in lotteryReconHeader on ltrd.ReconGUID equals ltrh.ReconGUID // Added on Nov 7,2017
select new ScratchGameDetailsModel()
{
ReconGUID = ltrd.ReconGUID,
GameGUID = ltrd.GameGUID,
GameNumber = lg.GameNumber ?? Constants.Zero,
GameName = lg.GameName ?? String.Empty,
GameUPC = lg.GameUPC ?? string.Empty,
GameBin = lg.GameBin ?? Constants.Zero,
StartCount = ltrd.StartCount,
EndCount = ltrd.EndCount,
CashierSales = ltrd.CashierSales,
ExpectedStartCount = ltrd.ExpectedStartCount,
QtyOnRoll = lg.QtyOnRoll ?? Constants.Zero,
BookNumber = (la == null || la.BookNumber == null ? string.Empty : la.BookNumber.Split(new char[] { '-' }, 2).ElementAt(1).TrimStart('-')),
ReconTimeStamp = ltrh.ReconTimeStamp // Added on Nov 7,2017
});
return response.AsQueryable();
}
您可能会说出为什么我不喜欢这种方法,其中无数个列表中有3个是数据库表的完整转储,后来又加入了这些表。当数据库增长时,这些变量的查询时间会增加。如果您问我,那就完全浪费资源了。由于大量的变量声明,我已经修复了一些方法,这些方法花费了超过5分钟的时间才能将数据填充到另一个表上,而现在它们在<1ms内完成。
这里是替换方法,除了现在包含一个子查询外,应该返回所有相同的方法。它还不再设置无数列表,而仅使用数据库上下文处理查询。这将引发错误,指出:
仅当未指定修剪字符作为参数时,LINQ to Entities中才支持方法'System.String TrimStart(Char [])'。
public virtual IQueryable<ScratchGameDetailsModel> GetScratchGameDetailsNew(string reconGUID)
{
var newResponse = (from ltrd in _context.LotteryReconDetail
join lg in _context.LotteryGame on ltrd.GameGUID equals lg.GameGUID
join la in _context.LotteryActivation
on new
{
lg.GameGUID,
BookNumber =
((from la in _context.LotteryActivation
where la.GameGUID == lg.GameGUID
orderby la.row_id descending
select new { la.BookNumber }).FirstOrDefault().BookNumber)
}
equals new { la.GameGUID, la.BookNumber } into la_join
from la in la_join.DefaultIfEmpty()
join ltrh in _context.LotteryReconHeader on ltrd.ReconGUID equals ltrh.ReconGUID
where ltrd.ReconGUID == reconGUID
select new ScratchGameDetailsModel()
{
ReconGUID = ltrd.ReconGUID,
GameGUID = ltrd.GameGUID,
GameNumber = lg.GameNumber ?? Constants.Zero,
GameName = lg.GameName ?? String.Empty,
GameUPC = lg.GameUPC ?? string.Empty,
GameBin = lg.GameBin ?? Constants.Zero,
StartCount = ltrd.StartCount,
EndCount = ltrd.EndCount,
CashierSales = ltrd.CashierSales,
ExpectedStartCount = ltrd.ExpectedStartCount,
QtyOnRoll = lg.QtyOnRoll ?? Constants.Zero,
BookNumber = (la == null || la.BookNumber == null ? string.Empty : la.BookNumber.Split(new char[] { '-' }, 2).ElementAt(1).TrimStart('-')),
ReconTimeStamp = ltrh.ReconTimeStamp
});
return newResponse.AsQueryable();
}
使用我的方法,如果我使用相同的操作(如设置变量)并将其用于查询,则会收到“对象引用未设置为对象的实例”。尤里卡!但为什么?相同的原始SQL查询没有问题,我非常想知道LINQ在使用数据库上下文与可查询/可枚举上下文之间的区别。
我还修改了这些变量声明,并使用AsQueryable()而不是AsEnumerable(),这样就不会转储整个列表,而是将其用作查询中的数据库上下文。如果我没记错的话,那是可枚举和可查询之间的显着区别。
此问题已解决,如@TheGeneral所指出。呼叫分配已更新,可以根据需要处理值调整。
BookNumber = (la == null || la.BookNumber == null ? string.Empty : la.BookNumber),
然后更新了调用方法以处理修剪
var scratchGameDetails = _lotteryReconService.GetScratchGameDetailsNew(reconGUID).ToList().Select(s => new
{
s.ReconGUID,
s.GameGUID,
s.GameNumber,
s.GameName,
s.GameUPC,
s.GameBin,
s.StartCount,
s.EndCount,
s.CashierSales,
s.ExpectedStartCount,
RangeStart = gameStartCount,
RangeEnd = useBaseZero ? (s.QtyOnRoll - 1) : s.QtyOnRoll,
BookNumber = (s.BookNumber == string.Empty ? string.Empty : s.BookNumber.Split(new char[] { '-' }, 2).ElementAt(1).TrimStart('-')),
s.ReconTimeStamp
}).OrderByDescending(x => x.ReconTimeStamp).Distinct();
答案 0 :(得分:0)
一个正在使用的内存数据(存储库代码(长叹气))
另一种将投影推回数据库的状态,这是正在破坏的数据库
引发此异常的全部原因是因为数据库不了解string.Trim()
的概念,而Split
也将引发
但是,我们可以使用任何String Canonical Functions ..,尽管最简单的方法只是项目,因为您要处理内存中需要事后处理的字符串操作
BookNumber = (la == null || la.BookNumber == null ? string.Empty : la.BookNumber,
请注意,我们可以将LTRIM
用作EntityFunctions
,但是只会修剪空间。再次看到String Canonical Functions