1

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

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

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

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

4

2 回答 2

7

GetAllWithChildren遇到N+1问题,在您的特定情况下,这表现特别糟糕。您的问题不清楚您正在尝试什么,但您可以尝试以下解决方案:

使用filter参数GetAllWithChildren

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

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

执行查询,然后加载关系

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

// 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 问题,因为它只执行两个数据库查询。

于 2016-07-27T08:30:18.263 回答
0

另一种手动加载关系的方法

想象一下我们有这些类:

public class Parent
{
    [PrimaryKey, AutoIncrement] public int Id { get; set; }
    public string Name { get; set; }

    public List<Child> children { get; set; }

    public override bool Equals(object obj)
    {
        return obj != null && Id.Equals(((BaseModel) obj).Id);
    }
    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

public class Child
{
    [PrimaryKey, AutoIncrement] public int Id { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }
}

提示这些类具有一对多的关系。那么它们之间的内部连接将是:

        var parents = databaseSync.Table<Parent>().ToList();
        var children = databaseSync.Table<Child>().ToList();

        List<Parent> parentsWithChildren = parents.GroupJoin(children, parent => parent.Id, child => child.ParentId,
            (parent, children1) =>
            {
                parent.children = children1.ToList();
                return parent;
            }).Where(parent => parent.children.Any()).ToList();
于 2020-03-11T11:06:56.463 回答