数据层的良率回报
我有一个 WPF 应用程序,它显示 DataGrid (XCeed DataGrid) 中的项目。当数据库(SQLite)包含大量项目时,应用程序需要一段时间才能加载,因此如果可能的话,我想使用yield return来按需加载这些项目。我知道 XCeed DataGrid 支持 UI 虚拟化,但我不完全确定如何转换以下同步代码块。
目前,列表加载在BackgroundWorker 中以防止UI 变慢,并将其填充为网格的数据源。
public override IList<IRecipe> GetRecipes()
{
List<IRecipe> recipes = new List<IRecipe>();
Execute(conn =>
{
using (var cmd = conn.CreateCommand()) {
cmd.CommandText = "SELECT * FROM recipes ORDER BY Name";
var reader = cmd.ExecuteReader();
while (reader.Read()) {
try {
var recipe = GetRecipe(reader);
recipes.Add(recipe);
} catch (Exception ex) {
Console.WriteLine(string.Format("Error loading recipe: {0}", ex.Message));
}
}
reader.Close();
cmd.CommandText = "SELECT * FROM Ingredients WHERE Recipe = @Recipe";
cmd.Parameters.AddWithValue("@Recipe", string.Empty);
foreach (IRecipe recipe in recipes) {
cmd.Parameters["@Recipe"].Value = recipe.ID;
reader = cmd.ExecuteReader();
while (reader.Read()) {
try {
IIngredient Ingredient = GetIngredient(reader);
recipe.Ingredients.Add(Ingredient);
} catch (Exception ex) {
Console.WriteLine(string.Format("Error adding Ingredient to recipe '{0}': {1}", recipe.Name, ex.Message));
}
}
reader.Close();
}
}
或者还有其他方法可以提高速度并使用延迟加载吗?
I have a WPF application which shows items in a DataGrid (XCeed DataGrid). The app takes a while to load when the database (SQLite) contains lots of items, so I'd like to use yield return if possible to load these on demand. I know the XCeed DataGrid supports UI virtualization, but I'm not entirely sure how to convert the following block of synchronous code.
Currently, the list of loaded in a BackgroundWorker to prevent UI slowdown, the populated as the grid's DataSource.
public override IList<IRecipe> GetRecipes()
{
List<IRecipe> recipes = new List<IRecipe>();
Execute(conn =>
{
using (var cmd = conn.CreateCommand()) {
cmd.CommandText = "SELECT * FROM recipes ORDER BY Name";
var reader = cmd.ExecuteReader();
while (reader.Read()) {
try {
var recipe = GetRecipe(reader);
recipes.Add(recipe);
} catch (Exception ex) {
Console.WriteLine(string.Format("Error loading recipe: {0}", ex.Message));
}
}
reader.Close();
cmd.CommandText = "SELECT * FROM Ingredients WHERE Recipe = @Recipe";
cmd.Parameters.AddWithValue("@Recipe", string.Empty);
foreach (IRecipe recipe in recipes) {
cmd.Parameters["@Recipe"].Value = recipe.ID;
reader = cmd.ExecuteReader();
while (reader.Read()) {
try {
IIngredient Ingredient = GetIngredient(reader);
recipe.Ingredients.Add(Ingredient);
} catch (Exception ex) {
Console.WriteLine(string.Format("Error adding Ingredient to recipe '{0}': {1}", recipe.Name, ex.Message));
}
}
reader.Close();
}
}
Alternatively is there any other way I could improve the speed and use lazy loading?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
yield return
在这里不是你的朋友。迭代器块(yield return
创建的内容)只是语法糖,用于创建实现 IEnumerable 的类和实现状态机的自定义枚举器。这实际上并没有提供任何性能优势,也不一定有利于延迟加载,因为它生成的代码将与您在其中编写的代码一样同步。我不是 Xceed 网格方面的专家,所以我无法为您提供该产品特有的答案,但延迟加载确实可能有助于解决您的问题(要真正解决它,您可能必须加载为尽可能少地显示数据,然后开始在后台线程中抢先加载即将到来的数据,但如何做到这一点的细节超出了此处答案的范围)。
一种方法可能是同步加载特定数量的行(无论当时需要显示什么),然后根据需要加载其余行(如果您的数据集很大并且用户不太可能查看所有行)它们)或在后台(如果集合不大或者用户可能会查看全部)。
yield return
is not your friend here. An iterator block (which is whatyield return
creates) is simply syntactic sugar for creating a class that implementsIEnumerable
and a custom enumerator that implements a state machine. This does not actually provide any performance benefit, nor does it necessarily facilitate lazy loading, as the code that it generates will be just as synchronous as the code that you write in it.I'm not an expert on the Xceed grid, so I can't provide you with an answer that's particular to that product, but lazy loading may indeed help with your problem (to solve it truly, you'll probably have to load as little data as possible to display, then start preemptively loading upcoming data in a background thread, but the details of how to do that are beyond the scope of an answer here).
One approach might be to synchronously load a particular number of rows (whatever is necessary to display at the time), then load the remainder of the rows either as needed (if your data set is large and the user is unlikely to look at all of them) or in the background (if the set is not large or the user is likely to review them all).
我不太熟悉 xceed 如何获取虚拟化项目。
我假设它是由某种事件指定所请求的行范围。
如果发生(或使用任何方法),您将获取查询的范围。使用
LIMIT
和OFFSET
,如 底部所述选择
文档。I'm not familiar exactly with how xceed fetches the virtualized items.
I assume it is by some kind of event that specifies what range of rows that are requested.
In the event (or whatever method that is used) you fetch a range of your query. Use
LIMIT
andOFFSET
as noted at the bottom of theSELECT
documentation.