我有以下内容并希望实现分页,但这样做时出现错误。仅当我从列表(或 IEnumerable)创建 IQueryable 时,当我直接对从 LINQ 作为 IQueryable 返回的查询结果执行分页时,我不会收到此错误
System.InvalidOperationException:源 IQueryable 未实现 IDbAsyncEnumerable。只有实现 IDbAsyncEnumerable 的源才能用于实体框架异步操作。有关更多详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=287068
List<WeeklyBilling> wbs = new List<WeeklyBilling>();
foreach (Trucks t in trucks)
{
WeeklyBilling wb = new WeeklyBilling();
wb.Customer = t.Customer;
wbs.Add(wb);
}
var wbitems = await wbs.AsQueryable<WeeklyBilling>()
.OrderBy(input.Sorting)
.PageBy(input)
.ToListAsync();
Run Code Online (Sandbox Code Playgroud) 我曾多次尝试寻找差异,并且有多种答案。
众所周知的区别之一是IEnumerable从内存中过滤数据,而IQueryable在服务器端进行。
这究竟是什么意思?
对内存数据进行过滤是否仍然是服务器端的事情?
我试图在多个地方寻找它们的用途,但我无法用简单的语言找到它。
谢谢你。
因此,当我为 DbContext 编写查询时,可查询的顺序实际上代表了输出查询。例如:
_dbContext
.Table
.OrderBy(i => i.Date)
.Take(25)
.Where(i => i.Variable == "something")
.ToList()
Run Code Online (Sandbox Code Playgroud)
相对
_dbContext
.Table
.Where(i => i.Variable == "something")
.OrderBy(i => i.Date)
.Take(25)
.ToList()
Run Code Online (Sandbox Code Playgroud)
因此,这些查询是不同的,因为第一个查询按日期获取最后 25 个项目并执行 where 子句。但另一个从where的结果中取出25。
当它被执行时,它会保持这个顺序吗?或者这就像一个构建器,其中所有属性都被设置和执行。如果我查看普通的 SQL,我无法在同一查询中的TAKE之前进行操作。WHERE所以对我来说这是有道理的。
我感到困惑的原因是,如果我用 MS SQL 编写第一个查询,我们会得到以下结果:
SELECT TOP 25 * FROM `Table` WHERE `Variable` = 'something' ORDER BY `Date`
Run Code Online (Sandbox Code Playgroud)
其中从 where 结果中取出 25。
出于性能原因,我的许多服务现在都返回 IQueryables,因此调用者可以在它们被具体化之前决定要过滤哪些元素。出于设计原因(接口等),我更愿意返回 IEnumerables,但这确实消除了 IQueryables 的优点:完整结果集的物化加上没有-Async方法。
我已经开始编写一些更喜欢 IQueryable 而不是 IEnumerable 的扩展方法,例如:
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Expression<Func<TSource, bool>> predicate)
=> source is IQueryable<TSource> ? Queryable.Where(source as IQueryable<TSource>, predicate) : Enumerable.Where(source, predicate.Compile());
public static Task<TSource[]> ToArrayAsync<TSource>(this IEnumerable<TSource> source)
=> (source as IQueryable<TSource>)?.ToArrayAsync() ?? Task.FromResult(source.ToArray());
Run Code Online (Sandbox Code Playgroud)
我不能是唯一一个思考这个问题的人。这些方法有什么改进吗?是否已经有一个很好的收藏/解决方案?或者这是一个糟糕的设计?所以请告诉我原因。
谢谢!
我认为IQueryable <T>是从IEnumerable中获得的<T>,所以为什么我不能像记录集合一样访问我的查询结果?
public bool DoLogIn(System.String strUserName, System.String strPassword)
{
if (this.IsLoggedIn)
return false;
ASRDBDataContext ASRData = new ASRDBDataContext();
IQueryable<user> CurrUser =
from usr in ASRData.users
where usr.userName == strUserName
where usr.password == strPassword
select usr;
if (CurrUser.Count() != 1)
return false;
this.CurrUserID = CurrUser[0].userID; // Error
return true;
}
Run Code Online (Sandbox Code Playgroud)
返回的错误是:"无法将带有[]的索引应用于类型为'System.Linq.IQueryable <user>' 的表达式"
我将填充的SelectList传递给我的View,我想将所选值默认为列表中的最后一条记录.到目前为止我有:
IQueryable<BuildNumber> projBuildNos = tcRepository.GetProjectBuildNos();
BuildList = new SelectList(projBuildNos, "ID", "value", projBuildNos.Last().ID);
Run Code Online (Sandbox Code Playgroud)
我得到一个例外说"查询运算符'Last'不受支持但我似乎无法获取我的通用列表中的最后一条记录,但找不到任何示例.
此代码来自"表单视图模型",将选择列表从我的存储库传递回视图,我想我应该在这里执行此操作.不过我是generics/mvc/linq的新手,所以我很乐意接受其他建议.
在此先感谢您的帮助.如果您想了解更多信息,请与我们联系.
比如说我想在我的存储库中创建一个方法
public IQueryable<Item> GetAllItemsByRange(int start, int end)
Run Code Online (Sandbox Code Playgroud)
然后我只想传递像(1,100),(101,200),(201,300)等,所以我只能回到那个范围,而不必一次得到所有的一切
谢谢!
所以,我有以下代码:
private readonly Dictionary<string, IGame> _gameLookup = new Dictionary<string, IGame>();
public T LookupGame<T>(string name) where T : IGame
{
if (name == null) throw new ArgumentNullException("name");
Type t = typeof(T);
if (_gameLookup.Any(d => d.Key == name))
{
return (T)_gameLookup[name];
}
var newInstance = (T)AppDomain.CurrentDomain.GetUnityContainer().Resolve(t, name);
if (newInstance != null)
{
_gameLookup.Add(name, newInstance);
return newInstance;
}
return default(T);
}
public IQueryable<T> ListGames<T>() where T : IGame
{
var games = _gameLookup.Where(d => d.GetType() == typeof (T));
return (IQueryable<T>) games;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是ListGames方法.(LookupGame方法只是包含在我正在做的事情的某些上下文中.) …
我有一个DbSet<Items>集合.
主键是Guid.我不想通过这个主键订购.我想通过名为"Order"的可编辑十进制属性进行排序.
我所拥有的代码非常简单,在用户将"$ top"参数放入请求之前,它非常有用:
public class ItemsController : ApiController
{
protected DbContext ctx = // ...
// GET api/documents
[EnableQuery()]
public IQueryable<Item> Get()
{
return ctx.Items.OrderBy(o => o.Order).AsQueryable();
}
Run Code Online (Sandbox Code Playgroud)
当用户将"$ top"放入查询字符串时,订单会全部搞乱(这可能会强制排序由主键完成,以获得一致的分页结果 - 但是,在我的情况下,这是相反的效果,它阻止我有一致的分页结果).
我已经尝试过移动.AsQueryable()到查询的早期(在.OrderBy(...)子句之前),我已经尝试过没有了.AsQueryable(),我已经尝试了两个AsQueryables等.
这个表中会有很多项目,所以需要通过一个来完成IQueryable(枚举Web服务器上的所有项目IEnumerable都不是一个选项).
到目前为止唯一有用的是从客户端传递"$ orderby = Order",但我不想强迫它(似乎很容易被遗忘).
1.)我可以做些什么来使我的Order财产订购这里的默认行为?
2.)或者失败了,无论如何,是否有人欺骗WebApi/OData认为自定义了"$ orderby = Order"子句?
我知道这样IQueryable做的好处是可以在服务器上运行过滤器,而不是在内存中加载所有记录IEnumerable,但是如何在代码中看起来如此,例如,如果我有这样的代码:
var data = context.Books.Where(x => x.Id > 930);
Run Code Online (Sandbox Code Playgroud)
如果我有1000条记录,那么它只会加载70条记录,并迭代它们,我转换data为List:
var list = data.ToList(); //has only 70 records
Run Code Online (Sandbox Code Playgroud)
但IEnumerable如果必须首先通过所有记录,那么加载所有记录的情况是什么,IQueryable即获得IEnumerable上述示例的版本:
var eData = context.Books.Where(x => x.Id > 930).ToList();
Run Code Online (Sandbox Code Playgroud)
他们不一样吗?最后一个代码只是组合上面两行代码?
iqueryable ×10
c# ×9
linq ×6
ienumerable ×5
.net ×2
generics ×2
linq-to-sql ×1
odata ×1
repository ×1