如何有条件地选择具有可查询linq的哈希集中的项目?
您好我是新来的C#,发现这个代码从互联网:如何有条件地选择具有可查询linq的哈希集中的项目?
public class InMemoryObjectSet<T>
: IObjectSet<T> where T : class
{
readonly HashSet<T> _set;
readonly IQueryable<T> _queryableSet;
public InMemoryObjectSet(IEnumerable<T> entities)
{
_set = new HashSet<T>();
foreach (var entity in entities)
{
_set.Add(entity);
}
_queryableSet = _set.AsQueryable();
}
public Expression Expression
{
get { return _queryableSet.Expression; }
}
public IQueryProvider Provider
{
get { return _queryableSet.Provider; }
}
public IEnumerator<T> GetEnumerator()
{
return _set.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/* Ignore Add, Delete operations */
}
我试图找到InMemoryObjectSet与条件名称的元素是“XX”。当然,我可以使用的IEnumerator遍历,但我只是想知道是否可以使用LINQ上下的方式:
var inMemoryItems = new InMemoryObjectSet<Customer>();
System.Linq.Expressions.Expression<Customer> exp = (x => x.Name == "xx");
var findItem = inMemoryItems.Provider.CreateQuery<Customer>(exp);
错误:
Cannot convert lambda expression to type 'Customer' because it is not a delegate type
任何人可以请帮助?
您想创建一个Expression
,可用于过滤您的Customers
集合。
您的错误是您的表情签名不正确。
我花了一段时间才看到您的InMemoryObjectSet<T>
的目的。 HashSet already implements
IEnumerable`,因此可能已经处理了所有你想要的LINQ语句。
但很显然,你想实现IQueryable<T>
一类,所以如果你想从一个IQueryable你需要以下类型的表达式过滤掉类型TSource的某些元素,你可以处理你的InMemorySet对象AsQueryable
:
Expression<Func<TSource, bool>> expr = ...
一旦你创建你的表情,你可以过滤IObjectSet<TSource>
仅包含符合您的表达式中的元素进行IQueryable<TSource>
。
IObjectSet<TSource>
implements IQueryable<TSource>. An
IQueryable`隐藏您要查询的集合的位置以及集合中元素的访问方式。
集合可以位于数据库,文件,互联网或InMemoryObjectSet中。
因为这个信息隐藏的,你真的没有知道你的项目的集合查询所在,以及如何访问(SQL?其他的方法?)
每个IQueryable
包含Expression
和一个Provider
。 Expression
通常由您使用LINQ语句填充。 “提供者”的任务是将Expression
转换为底层集合理解的格式并将其发送到此底层集合。
对于数据库的Provider
将翻译Expression
到SQL,对于InMemorySet
翻译会更简单,它会在一个IEnumerable翻译表达访问底层HashSet的。
看到这个,你不应该访问Provider
。您只应创建Expression
并使用execution子手方法(如ToList()
,First()
,Any()
,Count()
)执行Expression
并获得结果。
回到你的问题。正确的用法是: (在婴儿的步骤,所以你可以看到所有的基础类型)
InMemorySet<Customer> customerCollection = new InMemorySet<Customer>();
IQueryable<Customer> customers = customerCollection;
从这里,你不知道了你的客户是否在数据库 一个文件,InMemorySet
,或任何。 因为这些信息隐藏在下面的代码可以在任何这些集合
获取所有客户的名字XX,使用正确的LINQ:
IQueryable<Cusomter> xxCustomers = customers.Where(customer => customer.Name == XX);
使用ToList()
或类似
或者执行查询:创建一个Expression
并将其用于您的过滤功能:
string XX = ...
Expression<Func<Customer, bool>> expr = customer => customer.Name == XX;
IQueryable<Customer> result1 = customers.Where(expr);
ToList()
将命令提供者result1执行表达式。
一个非常低的水平的方法是告诉提供商访问
// (2) Use the Provider
IQueryProvider provider = customers.Provider;
object query2 = provider.Execute(customers.Expression)
但再次声明:不这样做,你就失去了信息隐藏,导致它不再保证你的代码适用于任何IQueryable
为什么不只是'_queryableSet.Whre(x => x.Name ==“xx”)''? –
没有特别的原因,只是一个条件样本。 – LOUDKING