包含问题的实体框架Linq

时间:2016-08-30 16:20:40

标签: c# entity-framework linq

我有以下架构:

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_iddoctype_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无法判断的值是否存在(我至少需要关键字的标签)在屏幕上打印)

1 个答案:

答案 0 :(得分:0)

感谢Lajos评论的反馈,我回到了绘图板(一个人去了白板)并重新编写了这个功能。我已将查询分解为两个查询。第一个返回与搜索条件匹配的docmaster_id列表,第二个用于填写关联的关键字,无论是否存在值(我至少需要在屏幕上打印关键字的标签)