繁体   English   中英

使用谓词加入LINQ查询

[英]Join LINQ-query with predicate

我在C#中使用LINQ查询时遇到了一些问题。

我在数据库中有相同结构的相同表。 所以,今天,我一直在困扰我的LINQ查询。

更多细节,我想使用谓词连接一些表。

我有一个有两个参数的函数。 第一个参数是某种Context(例如,它可能是ProductContext,CarContext,CatContext等)。

第二个参数是List<something> ,我将与我的第一个参数 - Context连接。

我不想要一套方法。

我添加了样本:

    public Element[] GetByIds( MyPredicateContext, Guid[] ids)
    {
        return 
            from id in ids
            join element in MyPredicateContext on id equals element.Id
            select
                new Element
                {
                    Id = element.Id,
                    Description = element.JobDescription,
                };
    }

如果查询是正确的,我可以看到的一个基本问题是返回类型是Element数组,而您尝试返回IEnumerable。 也许在结果集上执行.ToArray()可能会解决问题。

为什么不

return MyPredicateContext.Where(element=>ids.Contains(element.Id))
          .Select(e=>new Element()
             {
                 Id = element.Id, 
                 Description = element.JobDescription
             }).ToArray();

首先,你不能从一个数组创建一个新的IQueryable,这将恢复内存中的所有内容并在那里进行过滤。 当您使用SQL执行LINQ时,您正在处理表达式而不是c#代码,这只适用于内存中的东西(IEnumerable)。 如果您这样做,您的查询将在SQL中工作

from element in MyPredicateContext
where ids.Contains(element.Id)
select  new Element
                {
                    Id = element.Id,
                    Description = element.JobDescription,
                }

给定IQueryable的类型,其中T是接口或类。 结束方法看起来像这样

public interface IElement
        {
            Guid Id { get; }
            string JobDescription { get; }
        }

        public Element[] GetByIds<T>(IQueryable<T> myPredicateContext, Guid[] ids) where T:IElement
        {
            return (from element in myPredicateContext
                    where ids.Contains(element.Id)
                    select new Element
                                    {
                                        Id = element.Id,
                                        Description = element.JobDescription,
                                    }).ToArray();

        }

有一些方法可以做到没有泛型,但它们更先进,将难以维护。

这是一个适用于所有T类型的方法,正确的IQueryable将产生良好的sql,就像我指出的更高级,你需要查找表达式如何工作。

public static Element[] GetById<T, Tkey>(IQueryable<T> items,Tkey[] ids)
        {
            var type = typeof(T);
            ParameterExpression param = Expression.Parameter(type);
            var list = Expression.Constant(ids);
            //The names of the properties you need to get if all models have them and are named the same and are the same type this will work
            var idProp = Expression.Property(param, "Id");
            var descriptionProp = Expression.Property(param, "JobDescription");

            var contains = typeof(Enumerable).GetMethods().First(m => m.Name == "Contains" && m.GetParameters().Count() == 2).MakeGenericMethod(typeof(Tkey));
            var where = Expression.Lambda<Func<T, bool>>(Expression.Call(contains, list, idProp), param);

            return (items.
                Where(where).
                Select(Expression.Lambda<Func<T, Element>>(
                    Expression.MemberInit(
                    Expression.New(typeof(Element)),
                        Expression.Bind(typeof(Element).GetProperty("Id"), idProp),
                        Expression.Bind(typeof(Element).GetProperty("Description"), descriptionProp)), 
                        param))).ToArray();
        }

调用GetById(items, new Guid[] { Guid.NewGuid() })

暂无
暂无

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

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