C#SQLiteDataAdapter填充方法很慢

时间:2017-09-25 11:31:19

标签: c# wpf sqlite observablecollection

问题域是我有一个包含~90000行和6列的db文件。我有一个Select查询,在那里我获得了我所需的所有行和列,并且工作正常。现在是我用这些记录填充DataTable的东西。我使用SQliteDataAdapter Fill Method执行此操作,这需要大约1,3秒,然后我用这些数据填充我的ObservableCollection(< - Bound to DataGrid),这也需要约1,3秒。所以这是我的代码

private void GetSelectedMaterial()
    {
        DataTable dtMaterial = new DataTable();
        materialColl.Clear(); // Clearing ObservableCollection

        Trace.WriteLine("GetSelectedMaterial TS " + DateTime.Now + DateTime.Now.Millisecond);
        using (SQLiteConnection connection = new SQLiteConnection(dbConnection))
        using (SQLiteCommand cmd = connection.CreateCommand())
        {
            connection.Open();

            query = "SELECT * FROM Tbl_Materialliste LEFT JOIN(SELECT * FROM Tbl_Besitzt k WHERE k.TechnikID = '" + teTechnikID + "') as k ON k.MaterialID = Tbl_Materialliste.MaterialID";

            dataAdapter = new SQLiteDataAdapter(query, connection);
            Trace.WriteLine("query: " + DateTime.Now + DateTime.Now.Millisecond);

            dtMaterial.Columns.Add("Checked", typeof(bool));
            Trace.WriteLine("here comes the fill: " + DateTime.Now + DateTime.Now.Millisecond);
            dataAdapter.Fill(dtMaterial);

            Trace.WriteLine("Checkbox: " + DateTime.Now + DateTime.Now.Millisecond);
            DetermineCheckBox(dtMaterial, teTechnikID, 8);
            Trace.WriteLine("SQL TS: " + DateTime.Now + DateTime.Now.Millisecond);
        }

        FillMaterialColl(dtMaterial);
    }

    private void FillMaterialColl(DataTable dtMaterial)
    {
        foreach (DataRow dr in dtMaterial.Rows)
        {
            Material mat = new Material();

            mat.isChecked = (bool)dr.ItemArray[0];
            mat.materialID = (string)dr.ItemArray[1];
            mat.materialkurztext = (string)dr.ItemArray[2];
            mat.herstellername = (string)dr.ItemArray[3];
            mat.herArtikenummer = (string)dr.ItemArray[4];
            mat.dokument = (string)dr.ItemArray[5];
            mat.substMaterial = (string)dr.ItemArray[6];

            materialColl.Add(mat);
        }
    }

我知道ObservableCollections正在消耗性能但是有一些方法可以用另一种方式来做到这一点吗?有人说使用DataReader而不是DataAdapter,但DataAdapter应该使用DataReader,所以我认为性能没有任何改进。所以主要的问题是,如果显示新材料大约需要3-4秒,那么这个过程需要很长时间并且用户体验不是很好..

修改 所以这是我的数据库设计: enter image description here

这是Tbl_Material和Tbl_Technik之间的多对多关系 我的Select查询给了我来自Tbl_Material(~90k)的所有托管以及来自Tbl_Besitzt的那些我可以找到technikID的列 这样我就可以过滤(对于一个复选框),它属于我的MaterialID 在我的DB文件中,来自Tbl_Materialliste的MaterialId是一个PK,也是来自Tbl_Technik的TechnikID - 不是你想知道设计图像,我没有让他们进入模型..

非常感谢!

1 个答案:

答案 0 :(得分:0)

如果不了解数据库的架构和设计,就很难调查数据库的性能问题。在SQL查询中,有一个join表达式。您需要确保索引相应的数据字段,以便快速进行连接操作。这还取决于两个表的数据大小。

为了加快搜索结果的显示速度,您应该避免在ObservableCollection<T>中逐项添加它们。这是因为每次添加新项目时,绑定引擎都会将此项目传输到DataGrid,从而导致网格执行显示记录所需的所有操作。

如果您真的不需要集合是可观察的(例如,您不会在视图中添加或删除任何项目),那么只需将其设为IEnumerable<T>

public IEnumerable<Material> Materials
{
    get { return this.materials; }
    private set
    {
         // Using the PRISM-like implementation of INotifyPropertyChanged here
         // Change this to yours
         this.SetProperty(ref this.materials, value);
    }
}

在你的方法中,创建一个本地List<Material>,填充它,然后公开到视图:

List<Material> materials = new List<Material>();
// fill the list here
// ...
// finally, assign the result to your property causing the binding to do the job once
this.Materials = materials;

如果你需要ObservableCollection<T>,你可以做同样的伎俩 - 创建一个本地副本,填充它,最后公开。

如果这没有帮助,您应该尝试使用UI虚拟化。这是一个相当大的话题,但网上有很多信息。