我在以下代码中使用SQLite-Net Extensions从Sqlite数据库中检索1000行及其子关系:

var list =
SQLiteNetExtensions.Extensions.ReadOperations.GetAllWithChildren<DataModel>(connection);


问题是性能很尴尬。因为GetAllWithChildren()返回的列表不是可枚举的。是否存在使用Sqlite.net扩展将记录加载到Enumerable中的任何方法?

我现在使用Sqlite.net中的Table()方法,将获取的行加载到Enumerable中,但是我不想使用它,因为它不理解关系并且根本不加载子实体。

最佳答案

GetAllWithChildrenN+1 problem的影响,在您的特定情况下,这表现特别糟糕。您的问题尚不清楚,但是您可以尝试以下解决方案:

使用filter中的GetAllWithChildren参数:

您可以使用内部在内部执行filter查询的Table<T>().Where(filter)属性,而不是将所有对象都加载到内存中然后进行过滤,而SQLite-Net会转换为SELECT-WHERE子句,因此非常高效:

var list = connection.GetAllWithChildren<DataModel>(d => d.Name == "Jason");


执行查询,然后加载关系

如果查看GetAllWithChildren code,您将意识到它只是执行查询,然后加载现有关系。您可以自己执行此操作,以避免自动加载不需要的关系:

// Load elements from database
var list = connection.Table<DataModel>().Where(d => d.Name == "Jason").toList();
// Iterate elements and load relationships
foreach (DataModel element in list) {
    connection.GetChildren(element, recursive = false);
}


手动加载关系

要完全解决N + 1问题,您可以使用带有外键的Contains过滤器手动获取关系。这在很大程度上取决于您的实体模型,但是看起来像这样:

// Load elements from database
var list = connection.Table<DataModel>().Where(d => d.Name == "Jason").toList();
// Get list of dependency IDs
var dependencyIds = list.Select(d => d.DependencyId).toList();
// Load all dependencies from database on a single query
var dependencies = connection.Table<Dependency>.Where(d => dependencyIds.Contains(d.Id)).ToList();
// Assign relationships back to the elements
foreach (DataModel element in list) {
    element.Dependency = dependencies.FirstOrDefault(d => d.Id == element.DependencyId);
}


该解决方案解决了N + 1问题,因为它仅执行两个数据库查询。

10-04 21:06