实体框架Linq包含问题
本文关键字:问题 包含 Linq 框架 实体 | 更新日期: 2023-09-27 18:04:58
我有以下模式:
DMS_DocMaster {
docmaster_id int,
createddate datetime,
}
DMS_Master_Index {
doctype_id int
keyword_id int
docmaster_id int
}
DMS_DocTypes {
doctype_id int
group_id int
description varchar(50)
}
DMS_Keywords {
keyword_id int
label varchar(50)
datatype varchar(50)
}
DMS_Doc_Keyword_XRef {
doctype_id int
keyword_id int
seqorder int
}
在这个模式下,有一系列的文档组和文档类型(想象一下"桶"),用户可以将文档提交到其中。对于每种文档类型,都可以有一系列关键字(通过桥接XRef表)。当提交文档时,主ID存储在DocMaster
表中,关键字值存储在Master_Index
表中(以及master_id
和doctype_id
)。
我的问题是,我正在研究一个"搜索"查询-当用户导航到一个页面并按下搜索时,他们会看到一个动态生成的输入列表,其中包含"From Date"answers"Thru Date"以及该特定文档类型的所有关键字。当用户点击搜索按钮时,系统应该根据用户填写的所有可用值(允许空白值)进行查询。但是,我在构建链接到实体查询时遇到了麻烦。
目前为止我有什么:
public IList<DMS_DocMaster> SearchDocuments(int groupId = -1, int typeId = -1, DateTime? fromDate = null, DateTime? thruDate = null, Dictionary<int, string> searchCriteria = null)
{
List<DMS_DocMaster> results;
using (var ctx = new DMSEntities())
{
//make sure Lazy Loading is off because we are including reference tables in the results
//and the context will be closed at time of accessing reference tables --> exception thrown
ctx.Configuration.LazyLoadingEnabled = false;
//initial query regardless of type or not
//it's an anonymous type to make sure all fields are included
var res = from docMaster in ctx.DMS_DocMaster.Include(x => x.DMS_Notes)
join masterIndex in ctx.DMS_Master_Index on docMaster.docmaster_id equals masterIndex.docmaster_id
join docTypes in ctx.DMS_DocTypes on masterIndex.doctype_id equals docTypes.doctype_id
//join xref in ctx.DMS_Doc_Keyword_XRef on masterIndex.doctype_id equals xref.doctype_id
//join keys in ctx.DMS_Keywords on xref.keyword_id equals keys.keyword_id
where docTypes.group_id == groupId
//select new { docMaster, masterIndex, docTypes, xref, keys };
select new { docMaster, masterIndex, docTypes };
//if type is provided, search against the type
if (typeId > 0)
{
res = res.Where(i => i.docTypes.doctype_id == typeId);
}
//if there is a from date
if (fromDate.HasValue)
{
res = res.Where(i => i.docMaster.createdate >= fromDate.Value);
}
//if there is a thru date
if (thruDate.HasValue)
{
res = res.Where(i => i.docMaster.createdate <= thruDate.Value);
}
//if we have search criteria
if (searchCriteria != null)
{
//loop over it, appending where clauses
foreach (var criterion in searchCriteria)
{
res = res.Where(i => i.masterIndex.keyword_id == criterion.Key && i.masterIndex.keyword_value.Equals(criterion.Value));
}
}
//select just the Doc Master records from the anonymous type
//include the Master Index reference table, and the links to the Keywords table
//to get the keyword label
var res1 = res.Select(i => i.docMaster);
res1 = res1.Include(x => x.DMS_Notes);
res1 = res1.Include(x => x.DMS_Master_Index);
//res1 = res1.Include(x => x.DMS_Master_Index
// .Select(y => y.DMS_Doc_Keyword_XRef.DMS_Keywords));
res1 = res1.Include(x => x.DMS_Master_Index.Where(y => y.doctype_id == typeId)); //this throws an error
res1 = res1.OrderByDescending(i => i.createdate);
results = res1.ToList();
}
return results;
}
我遇到的问题是,无论文档类型如何,它都返回关键字的所有实例-我需要过滤Master_Index
表的.Include
,但它抛出ArgumentException
错误
Include路径表达式必须引用在该类型上定义的导航属性。引用导航属性使用点点路径,集合导航属性使用Select操作
如何修改我的Linq查询来搜索我提供的所有条件,并填充导航属性?如果可以,我希望避免对数据库进行多次查询。
感谢Lajos的评论反馈,我回到了绘图板(字面上说是白板)并重新编写了函数。我将查询分解为两个查询。第一个返回匹配搜索条件的docmaster_id
列表,第二个填写相关的keywords
,而不管值是否存在(我至少需要在屏幕上打印关键字的标签)
感谢Lajos的评论反馈,我回到绘图板上(实际上是到白板上)重新编写了这个函数。我将查询分解为两个查询。第一个返回与搜索条件匹配的docmaster_id的列表,第二个用于填写关联的关键字,而不管值是否存在(我至少需要关键字的标签在屏幕上打印)