.net 数据层的收益率

.net 数据层的收益率,.net,wpf,yield-return,xceed-datagrid,.net,Wpf,Yield Return,Xceed Datagrid,我有一个WPF应用程序,它显示DataGrid(XCeed DataGrid)中的项。当数据库(SQLite)包含大量项目时,应用程序需要一段时间才能加载,因此如果可能的话,我想使用yield return按需加载这些项目。我知道,但是我不完全确定如何转换下面的同步代码块 目前,在BackgroundWorker中加载了一个列表,以防止UI减速,该列表作为网格的数据源填充 public override IList<IRecipe> GetRecipes() {

我有一个WPF应用程序,它显示DataGrid(XCeed DataGrid)中的项。当数据库(SQLite)包含大量项目时,应用程序需要一段时间才能加载,因此如果可能的话,我想使用yield return按需加载这些项目。我知道,但是我不完全确定如何转换下面的同步代码块

目前,在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();
                }
            }
public覆盖IList GetRecipes()
{
列表配方=新列表();
执行(conn=>
{
使用(var cmd=conn.CreateCommand()){
cmd.CommandText=“按名称从配方顺序中选择*”;
var reader=cmd.ExecuteReader();
while(reader.Read()){
试一试{
var recipe=GetRecipe(读卡器);
配方。添加(配方);
}捕获(例外情况除外){
WriteLine(string.Format(“加载配方时出错:{0}”,例如Message));
}
}
reader.Close();
cmd.CommandText=“从配方=@Recipe的配料中选择*”;
cmd.Parameters.AddWithValue(“@Recipe”,string.Empty);
foreach(配方中的IRecipe配方){
cmd.Parameters[“@Recipe”].Value=Recipe.ID;
reader=cmd.ExecuteReader();
while(reader.Read()){
试一试{
iIngElement成分=获取成分(读取器);
配方。配料。添加(配料);
}捕获(例外情况除外){
WriteLine(string.Format(“向配方“{0}”添加成分时出错:{1}”,配方.Name,ex.Message));
}
}
reader.Close();
}
}

或者,是否有其他方法可以提高速度并使用延迟加载?

我不太熟悉xceed如何获取虚拟化项目。
我假设是通过某种事件指定请求的行的范围


在事件(或使用的任何方法)中,您获取查询的一个范围。使用
LIMIT
OFFSET
,如底部所述。

在这里不是您的朋友。迭代器块(这是
yield return
创建的)只是创建一个实现
IEnumerable
的类和一个实现状态机的自定义枚举器的语法糖。这实际上并没有提供任何性能优势,也不一定有助于延迟加载,因为它生成的代码与您在其中编写的代码一样同步

我不是Xceed网格方面的专家,因此我无法为您提供该产品特有的答案,但延迟加载确实可以帮助您解决问题(要真正解决这个问题,您可能需要加载尽可能少的数据来显示,然后开始在后台线程中抢先加载即将到来的数据,但是如何做到这一点的细节超出了这里的回答范围)


一种方法可能是同步加载特定数量的行(当时需要显示的任何行),然后根据需要(如果数据集很大,用户不太可能查看所有行)或在后台加载其余行(如果数据集不大或用户可能会查看所有行).

您真的需要直接加载所有内容吗?看起来是对的。问题是上一个免费版本(3.1)不支持。需要切换到WPF Toolkit DataGrid。@Echilon:您使用的是.NET的哪个版本?.NET 4.0将
DataGrid
作为标准
PresentationFramework
程序集的一部分;WPF Toolkit仅用于.NET 3.x。我已经有一段时间没有使用DataGrid了,这是用于较旧的应用程序。谢谢,tWPF DataGrid似乎提供了一个很有前途的替代解决方案,它使用了
异步虚拟化收集
,如下所述