[英]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:
模型看起来像这样:
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.