用谓词连接LINQ-query
本文关键字:LINQ-query 连接 谓词 | 更新日期: 2023-09-27 18:09:32
我在c#中使用LINQ查询遇到了一些问题。
我在数据库中有相同的表具有相同的结构。所以,今天,我一直在为我的LINQ查询烦恼。
更多细节,我想使用谓词连接一些表。
我有一个函数,它有两个参数。第一个参数是某种类型的上下文(例如,它可能是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,
};
}
如果查询是正确的,我可以看到的一个基本问题是返回类型是元素数组,而你试图返回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是接口或类。end方法看起来像这样
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();
}
Call GetById(items, new Guid[] { Guid.NewGuid() })