简体   繁体   English

使用Dynamic LINQ在一对多实体框架关系中的位置

[英]Using Dynamic LINQ Where in a one-to-many Entity Framework relationship

I am using EF 6 and .net 4.5. 我使用的是EF 6和.net 4.5。 I have a "Documents" table with the PK "DocumentId" (Int) and another column, "Title". 我有一个带有PK“DocumentId”(Int)的“Documents”表和另一列“Title”。 I have another table called "DocumentFilters" with the columns "DocumentId" (Int) and "DocGUID" (Guid). 我有另一个名为“DocumentFilters”的表,其中包含“DocumentId”(Int)和“DocGUID”(Guid)列。 There is a FK on "Doc Id" between the two tables. 两个表之间的“Doc Id”上有一个FK。 It is a one to many Id's relationship between the Documents and DocumentFilters tables. 它是Documents和DocumentFilters表之间的一对多Id关系。 The Model looks like this: 模型看起来像这样:

DocModel

I'm trying to write a Dynamic LINQ query using the DynamicLibrary.cs library from the NuGet package. 我正在尝试使用NuGet包中的DynamicLibrary.cs库编写动态LINQ查询。

With regular Linq, the query looks something like this in c#: 使用常规Linq,查询在c#中看起来像这样:

DocDBContext db = new DocDBContext();
var documents = db.Documents.Include(d => d.DocumentFilters);
Guid gTest = Guid.Parse("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");

documents = documents.Where(d => d.DocumentFilters.Select(f => f.DocGUID).Contains(gTest));

This works perfectly and retrieves the documents delimited by the GUID filter that I'm interested in. However, I need to place this within a filter string dynamically, where it may contain other filters. 这非常有效并且检索由我感兴趣的GUID过滤器分隔的文档。但是,我需要动态地将它放在过滤器字符串中,其中它可能包含其他过滤器。 Is it possible to do that? 有可能吗? I've tried code like: 我尝试过的代码如下:

documents = documents.Where("DocumentFilters.Select(DocGUID).Contains(@0)", gTest);

Error: No applicable aggregate method 'Select' exists 错误:不存在适用的聚合方法“选择”

or 要么

documents = documents.Where("DocumentFilters.DocGUID=@0", gTest);

Error: GUID property does not exist on DocumentFilters. 错误:DocumentFilters上不存在GUID属性。 (Which makes sense because DocumentFilters is a collection). (这是有道理的,因为DocumentFilters是一个集合)。

I also thought it might be worth to give this a shot: 我也认为值得这样做:

documents = documents.Where("DocumentFilters.AsQueryable().Select(DocGUID).Contains(@0)", gTest);

But again, it doesn't look like the library supports AsQueryable and throws Error: No applicable aggregate method 'AsQueryable' exists. 但同样,它看起来不像库支持AsQueryable并抛出错误:没有适用的聚合方法'AsQueryable'存在。

Is it possible to write such a restriction on a property of an enumerable object within the Documents table? 是否可以在Documents表中对可枚举对象的属性写入这样的限制?

So one solution was to modify Dynamic.cs by adding " Select " to the IEnumerableSignatures interface in the ExpressionParser class. 因此,一种解决方案是通过向ExpressionParser类中的IEnumerableSignatures接口添加“ Select ”来修改Dynamic.cs。 And additionally add it to the ParseAggregate() method: 另外将它添加到ParseAggregate()方法:

if (signature.Name == "Min" || signature.Name == "Max")
        {
            typeArgs = new Type[] { elementType, args[0].Type };
        }
        else if (signature.Name == "Select")
        {
            typeArgs = new Type[] { elementType, Expression.Lambda(args[0], innerIt).Body.Type };
        } 

However, after this I still needed to overload the Contains() method to work with GUIDs. 但是,在此之后我仍然需要重载Contains()方法以使用GUID。 I didn't bother to do that. 我没那么费心。 Instead I realized I can simply use the already supported .Any() instead of .Select() ! 相反,我意识到我可以简单地使用已经支持的.Any()而不是.Select()

documents = documents.Where("DocumentFilters.Any(DocGUID.Equals(@0))", gTest); //!!!

I also had to change the column name from " GUID " to " DocGUID " because when writing GUID.Equals() in the restriction string, the parser mistook it for the GUID type and not the column name, and threw the error that Equals() is not a valid extension for the type GUID. 我还必须将列名从“ GUID ”更改为“ DocGUID ”,因为在限制字符串中写入GUID.Equals()时,解析器将其误认为是GUID类型而不是列名,并抛出了Equals()的错误Equals()不是GUID类型的有效扩展名。

Sorry for wasting everyone's time! 很抱歉浪费每个人的时间!

尝试使用Dynamic Linq ,它可以用于对抗字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM