【发布时间】:2018-01-03 14:50:33
【问题描述】:
我有一个记录电话查询和建议的 wpf mvvm 应用程序。
我正在尝试查询通话记录以获取相关实体中的信息,但性能很慢。
Call--1:M--CallQuery--M:M--AnswerDoc--1:M--AnswerDocSection
1:M|M:1
CallQueryAnswerDoc
因此,调用将包含一个或多个查询(查询是一个问题及其答案),并且(答案)一个查询将引用 1 个或多个(最多 2 个)AnswerDocsSections。每个 AnswerDocSection 都来自一个 AnswerDoc。创建 CallQueryAnswerDoc 表是为了处理 CallQuery 和 AnswerDoc 表之间的 M:M 联接。
为了准备一个常见问题解答,我正在尝试查询哪些调用使用了某些 AnswerDocs 和/或 AnswerDocSections。
对于我的第一种方法,我检索了一个 ObservableCollection 的呼叫,然后循环遍历每个呼叫以收集其 CallQueries 的 ObservableCollection,并且对于每个 CallQuery,检查 AnswerDocID 是否与 searchText 的 AnswerDocID 匹配。如果是这样,则将调用添加到返回的调用列表中。
在大约 5k 个调用的数据库中,这需要十多分钟,并且以每 10 秒大约 100 个调用的速度进行。
所以,接下来我尝试使用如下语法在 linq 查询中完成所有操作:
var qCQADS = callList.Where(c =>
c.CallQueries.Any(cq =>
cq.CallQueryAnswerDocs.Any(cqad =>
cqad.AnswerDocSectionID == CallSearch.AnswerDocSectionID)));
但令人惊讶的是(对我来说,无论如何)这似乎需要与newing ObservableCollections 一样多的时间。
我可以在 sql 中执行此查询并在 1 秒内获得结果。
SQL 查询
SELECT dbo.AnswerDoc.Code, dbo.AnswerDocSection.Title, dbo.Call.CallID,
dbo.Call.CallDate, dbo.Call.RegionID, dbo.Call.CallSubject
FROM dbo.AnswerDocSection
INNER JOIN dbo.CallQueryAnswerDocSection ON dbo.AnswerDocSection.AnswerDocSectionID =
dbo.CallQueryAnswerDocSection.AnswerDocSectionID
INNER JOIN dbo.CallQuery ON dbo.CallQueryAnswerDocSection.CallQueryID =
dbo.CallQuery.CallQueryID
INNER JOIN dbo.AnswerDoc ON dbo.AnswerDocSection.AnswerDocID = dbo.AnswerDoc.AnswerDocID
INNER JOIN dbo.Call ON dbo.CallQuery.CallID = dbo.Call.CallID
WHERE (dbo.AnswerDoc.Code = N'General')
AND (dbo.AnswerDocSection.Title = N'Invalid Username')
如何使用 wpf 实现这种性能?
【问题讨论】:
-
5000 行是 nothing,您确定您的相关表上有索引吗?在处理如此少的数据时,我通常更喜欢将 all 数据加载到我的应用程序中的缓存对象中,以避免往返数据库。
-
同意@Robert 的建议,您可以使用
Include,如here 所述。 -
@Robert :所有 ID 都是主键。正如我所说,在 Sql Server 中运行 sql 查询需要不到 1 秒的时间。
ObservableCollection的调用被传递给我的方法(linq 示例中的 callList),我的代码只是循环通过集合。我最初是后端,我认为这方面还可以。 -
@KeyurPATEL 我认为您可能正在做某事(令人震惊的是,我认为我之前在 SO 上犯过这个错误)。你想让你的评论成为答案吗?
-
在我所有的
Include()经验中,我从来不需要超过 2 个级别的深度,不过我会尽力而为 :)
标签: c# sql-server linq