我正在尝试编写一种通用的数据库更新方法,该方法可以利用IQueryable在处理之前减少返回的实体的数量。因此,对于一部分代码,我尝试了一下(b.ToType()
返回了P
):
IQueryable<B> bs = bcontext.Set<B>();
IQueryable<P> ps = pcontext.Set<P>();
List<P> inserts = ps.Except(bs.Select(b => b.ToType())).Take(500).ToList();
当我这样写的时候,我得到System.ArgumentNullException: 'Value cannot be null.'
但是,当我像这样进行Except
之前枚举DBSet时,它是可行的:
List<B> bs = bcontext.Set<B>().ToList();
List<P> ps = pcontext.Set<P>().ToList();
List<P> inserts = ps.Except(bs.Select(b => b.ToType())).Take(500).ToList();
两种方法都可以编译,但是我在第一种方法而不是第二种方法上遇到了异常。可以放入列表不存在的IQueryable表达式树的内容有什么限制吗?
答案 0 :(得分:2)
通常,IQueryable用于避免执行查询,直到将查询范围缩小到可以获取实际所需数据的确切位置为止。
与List相比,当我们执行.ToList()时,将执行查询,并将所有结果存储在内存中,您可以从中查询或过滤出结果。
取决于客户端的性能或网络,可以选择正确的选项。执行.ToList会将结果存储在内存中,您可以从该位置执行操作。
对于不适的参考文献,您将您重定向至此答案: Differences between IQueryable, List, IEnumerator?
答案 1 :(得分:2)
以下是IQueryable<T>.Except
的实现,请检查here:
public static IQueryable<TSource> Except<TSource>(this IQueryable<TSource> source1, IEnumerable<TSource> source2) {
if (source1 == null)
throw Error.ArgumentNull("source1");
if (source2 == null)
throw Error.ArgumentNull("source2");
return source1.Provider.CreateQuery<TSource>(
Expression.Call(
null,
GetMethodInfo(Queryable.Except, source1, source2),
new Expression[] { source1.Expression, GetSourceExpression(source2) }
));
}
IQueryable<T>
和List<T>
的主要工作区别在于,可查询类型在内部与Expression<Func<T>>
一起使用,因为在{{1 }}与List<T>
一起使用,因为它在内存中进行处理。当涉及到远程处理时,例如EF之类的内容会转换为相关的Sql查询以进行处理,而在您的情况下,以下内容将在远程处理中转换为Func<T>
:null
。
以下是bs.Select(b => b.ToType())
的实现,请检查here:
IEnumerable<T>.Except
public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first,
IEnumerable<TSource> second)
{
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return ExceptIterator<TSource>(first, second, null);
}
本身在内部是set操作,即使对Except
的{{1}}调用也会导致相同的异常。
您已经看到List<T>
的定义,这对于理解Except(null)
的处理很重要,Expression的主要作用是做什么,而Func的方法是检查{{ 3}}。
对于简单的IQueryable<T>.Except
,这就是Queryable表达式的样子(如附图所示)。
本质仍然存在,请检查您的提供程序在内部将Queryable Expression转换为什么,这将导致null并因此在处理时出现异常