LINQ to entity - 构建 where 子句以测试多对多关系中的集合 [英] LINQ to entities - Building where clauses to test collections within a many to many relationship

查看:12
本文介绍了LINQ to entity - 构建 where 子句以测试多对多关系中的集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我使用的是 Linq 实体框架.我有 2 个实体:ContentTag.它们之间是多对多的关系.Content 可以有很多 TagsTag 可以有很多 Contents.所以我试图编写一个查询来选择所有标签名称等于 blah

So, I am using the Linq entity framework. I have 2 entities: Content and Tag. They are in a many-to-many relationship with one another. Content can have many Tags and Tag can have many Contents. So I am trying to write a query to select all contents where any tags names are equal to blah

两个实体都将另一个实体的集合作为属性(但没有 ID).这是我挣扎的地方.我确实有一个用于 Contains 的自定义表达式(因此,无论谁可以帮助我,您都可以假设我可以为集合执行包含").我从:http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2670710&SiteID=1

The entities both have a collection of the other entity as a property(but no IDs). This is where I am struggling. I do have a custom expression for Contains (so, whoever may help me, you can assume that I can do a "contains" for a collection). I got this expression from: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2670710&SiteID=1

我最终找到了自己的答案.

推荐答案

阅读PredicateBuilder,阅读人们发送给我的所有精彩帖子,发布在其他网站上,然后在 组合谓词规范函数映射.. 哦,我从 在 LINQ 查询中调用函数(其中一些类取自这些页面).

After reading about the PredicateBuilder, reading all of the wonderful posts that people sent to me, posting on other sites, and then reading more on Combining Predicates and Canonical Function Mapping.. oh and I picked up a bit from Calling functions in LINQ queries (some of these classes were taken from these pages).

我终于有办法了!!!虽然有一块有点被黑了......

I FINALLY have a solution!!! Though there is a piece that is a bit hacked...

让我们用 :(

我不得不使用反射器并复制标记为内部的 ExpressionVisitor 类.然后我不得不对其进行一些小的更改,以使其正常工作.我必须创建两个异常(因为它是新的内部异常.我还必须更改 ReadOnlyCollection() 方法的返回:

I had to use reflector and copy the ExpressionVisitor class that is marked as internal. I then had to make some minor changes to it, to get it to work. I had to create two exceptions (because it was newing internal exceptions. I also had to change the ReadOnlyCollection() method's return from:

return sequence.ToReadOnlyCollection<Expression>();

致:

return sequence.AsReadOnly();

我会发布这门课,但它很大,我不想把这篇文章弄得比它本来就更乱.我希望将来可以从我的库中删除该类,并且 Microsoft 会将其公开.继续……

I would post the class, but it is quite large and I don't want to clutter this post any more than it's already going to be. I hope that in the future that class can be removed from my library and that Microsoft will make it public. Moving on...

我添加了一个 ParameterRebinder 类:

I added a ParameterRebinder class:

public class ParameterRebinder : ExpressionVisitor {
        private readonly Dictionary<ParameterExpression, ParameterExpression> map;

        public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map) {
            this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
        }

        public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp) {
            return new ParameterRebinder(map).Visit(exp);
        }

        internal override Expression VisitParameter(ParameterExpression p) {
            ParameterExpression replacement;
            if (map.TryGetValue(p, out replacement)) {
                p = replacement;
            }
            return base.VisitParameter(p);
        }
    }

然后我添加了一个 ExpressionExtensions 类:

Then I added a ExpressionExtensions class:

public static class ExpressionExtensions {
        public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge) {
            // build parameter map (from parameters of second to parameters of first)
            var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);

            // replace parameters in the second lambda expression with parameters from the first
            var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);

            // apply composition of lambda expression bodies to parameters from the first expression 
            return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
        }

        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) {
            return first.Compose(second, Expression.And);
        }

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) {
            return first.Compose(second, Expression.Or);
        }
    }

我添加的最后一个类是 PredicateBuilder:

And the last class I added was PredicateBuilder:

public static class PredicateBuilder {
    public static Expression<Func<T, bool>> True<T>() { return f => true; }
    public static Expression<Func<T, bool>> False<T>() { return f => false; }

}

这是我的结果...我能够执行此代码并从我正在搜索的标签中取回具有匹配标签"实体的结果内容"实体!

This is my result... I was able to execute this code and get back the resulting "content" entities that have matching "tag" entities from the tags that I was searching for!

    public static IList<Content> GetAllContentByTags(IList<Tag> tags) {
        IQueryable<Content> contentQuery = ...

        Expression<Func<Content, bool>> predicate = PredicateBuilder.False<Content>();

        foreach (Tag individualTag in tags) {
            Tag tagParameter = individualTag;
            predicate = predicate.Or(p => p.Tags.Any(tag => tag.Name.Equals(tagParameter.Name)));
        }

        IQueryable<Content> resultExpressions = contentQuery.Where(predicate);

        return resultExpressions.ToList();
    }

如果有人需要帮助,请告诉我,如果您希望我为此向您发送文件,或者只是需要更多信息.

Please let me know if anyone needs help with this same thing, if you would like me to send you files for this, or just need more info.

这篇关于LINQ to entity - 构建 where 子句以测试多对多关系中的集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆