SQLite.net Extensions多次加载同一个实体,而不是返回相同的引用

时间:2015-06-17 03:09:59

标签: entity-framework entity-framework-core sqlite-net-extensions

我在Windows 10通用应用程序中使用PCL版本的SQLite.Net Extensions。这是我第一次使用它。它通常似乎有效,但似乎是多次加载实体而不是重用对同一对象的引用。

根据SQLite.Net扩展文档:

  

SQLite-Net Extensions将确保任何对象仅从数据库加载一次,并将解决循环依赖关系和反向关系,同时保持整数引用。这意味着具有相同标识符的同一类的任何返回对象将是对完全相同对象的引用。

这似乎并没有发生在我身上。这是我的代码:

public class Group {
    [PrimaryKey, AutoIncrement]
    public Guid Id { get; set; }

    public string GroupName { get; set; }

    public override string ToString() {
        return string.Format("Group [ID: {0}, HashCode: {1}] GroupName={2}", Id.ToString().Last(4), GetHashCode(), GroupName);
    }

    [ManyToMany(typeof(GroupMember), CascadeOperations = CascadeOperation.CascadeRead)]
    public List<Member> Members { get; set; }

    public void DebugIt() {
        Debug.WriteLine(this);
        foreach (var member in Members) Debug.WriteLine("    " + member);
    }
}

public class Member {
    [PrimaryKey, AutoIncrement]
    public Guid Id { get; set; }

    public string Name { get; set; }

    public override string ToString() {
        return string.Format("Member [ID: {0}, HashCode: {1}] Name={2}", Id.ToString().Last(4), GetHashCode(), Name);
    }

    [ManyToMany(typeof (GroupMember), CascadeOperations = CascadeOperation.CascadeRead)]
    public List<Group> Groups { get; set; }

    public void DebugIt() {
        Debug.WriteLine(this);
        foreach (var group in Groups) Debug.WriteLine("    " + group);
    }
}

public class GroupMember {
    [PrimaryKey, AutoIncrement]
    public Guid Id { get; set; }
    [ForeignKey(typeof(Group))]
    public Guid GroupID { get; set; }
    [ForeignKey(typeof(Member))]
    public Guid MemberId { get; set; }
}

public class DatabaseGroups {
    private const string FileName = "db.sqlite";
    private SQLiteConnection _db;

    public async Task<bool> LoadAsync() {
        var exists = await FileHelper.DoesFileExistAsync(FileName);
        _db = new SQLiteConnection(new SQLitePlatformWinRT(), DatabaseFullPath,
            exists ? SQLiteOpenFlags.ReadWrite : SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite);
        if (!exists) InitializeWithDefaults();
        return await FileHelper.DoesFileExistAsync(FileName);
    }

    private void InitializeWithDefaults() {
        _db.CreateTable<Group>();
        _db.CreateTable<Member>();
        _db.CreateTable<GroupMember>();

        var group1 = new Group {GroupName = "Group 1"};
        var group2 = new Group {GroupName = "Group 2"};
        var member1 = new Member {Name = "Bob"};
        var member2 = new Member {Name = "Jane"};

        _db.Insert(group1);
        _db.Insert(group2);
        _db.Insert(member1);
        _db.Insert(member2);

        group1.Members = new List<Member> {member1, member2};
        _db.UpdateWithChildren(group1);

        group2.Members = new List<Member> {member1, member2};
        _db.UpdateWithChildren(group2);
    }

    private static StorageFolder DatabaseFolder {
        get { return ApplicationData.Current.LocalFolder; }
    }

    private static string DatabaseFullPath {
        get { return Path.Combine(DatabaseFolder.Path, FileName); }
    }

    public void DebugIt() {
        foreach (var groupId in _db.Table<Group>().Select(g => g.Id)) {
            var group = _db.GetWithChildren<Group>(groupId);
            group.DebugIt();
        }
        foreach (var memberId in _db.Table<Member>().Select(m => m.Id)) {
            var member = _db.GetWithChildren<Member>(memberId);
            member.DebugIt();
        }
    }
}

protected override async void OnLaunched(LaunchActivatedEventArgs e) {
    _db = new DatabaseGroups();
    await _db.LoadAsync();
    _db.DebugIt();

运行时,我会创建一些初始数据。然后我使用GetWithChildren加载这些对象并进行调试。结果如下:

Group[ID: 4858, HashCode: 51192825] GroupName = Group 1
    Member[ID: dbfa, HashCode: 64971671] Name = Jane
    Member[ID: b047, HashCode: 30776584] Name = Bob
Group[ID: 30f0, HashCode: 53439890] GroupName = Group 2
    Member[ID: dbfa, HashCode: 36062904] Name = Jane
    Member[ID: b047, HashCode: 9089598] Name = Bob
Member[ID: b047, HashCode: 20305449] Name = Bob
    Group[ID: 30f0, HashCode: 9648315] GroupName = Group 2
    Group[ID: 4858, HashCode: 29803642] GroupName = Group 1
Member[ID: dbfa, HashCode: 36899882] Name = Jane
    Group[ID: 30f0, HashCode: 23318221] GroupName = Group 2
    Group[ID: 4858, HashCode: 60865449] GroupName = Group 1

如您所见,对象似乎正确加载,但组1(例如)的对象引用不同(请参阅哈希代码)。

我是否可能误解了SQLite.Net Extensions处理对象引用的方式?也许它会在对GetWithChildren的单个调用中处理重用对象引用,但不会在同一个SQLiteConnection上的多个调用之间进行重用?

如果是这样的话,你应该如何用这些关系加载更复杂的对象图?

1 个答案:

答案 0 :(得分:1)

你是对的,SQLite-Net Extensions缓存对象以进行递归调用以避免引用循环和处理反向关系,但它不会在调用之间缓存对象。

SQLite-Net Extensions只是SQLite.Net上的一个薄层,如果整数引用对您很重要,您可以返回手动查询以进行更多复杂操作。

如果您有任何建议或拉取请求,我们随时欢迎您;)