我有以下架构:
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”和“Thru Date”as以及该特定文档类型的所有关键字。当用户点击搜索按钮时,系统应该根据用户填写的所有可用值进行查询(允许空白值)。但是,我在构建Linq-to-Entities查询时遇到问题。
到目前为止我所拥有的:
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;
}
我遇到的问题是它返回关键字的所有实例而不管文档类型 - 我需要过滤.Include
表的Master_Index
,但它会抛出ArgumentException
错误
Include路径表达式必须引用在类型上定义的导航属性。使用虚线路径作为参考导航属性,并使用选择操作进行集合导航属性
如何修改我的Linq查询以搜索我提供的所有条件,并填写导航属性?如果可以的话,我希望避免对数据库进行多次查询。
更新
感谢Lajos评论的反馈,我回到了绘图板(一个人去了白板)并重新编写了这个功能。我已将查询分解为两个查询。第一个返回与搜索条件匹配的docmaster_id
列表,第二个用于填写相关的keywords
无法判断的值是否存在(我至少需要关键字的标签)在屏幕上打印)
答案 0 :(得分:0)
感谢Lajos评论的反馈,我回到了绘图板(一个人去了白板)并重新编写了这个功能。我已将查询分解为两个查询。第一个返回与搜索条件匹配的docmaster_id列表,第二个用于填写关联的关键字,无论是否存在值(我至少需要在屏幕上打印关键字的标签)