Я использую версию SQLite.Net Extensions для PCL в универсальном приложении Windows 10. Это мой первый раз, когда я использую его. В целом кажется, что он работает, но он загружает объект несколько раз, а не повторно использует ссылку на один и тот же объект.
Согласно документации расширений SQLite.Net:
Расширения SQLite-Net гарантируют, что любой объект загружается из базы данных только один раз, и будут разрешать циклические зависимости и обратные отношения, сохраняя при этом интегральную ссылку. Это означает, что любой возвращенный объект того же класса с тем же идентификатором будет ссылкой на точно такой же объект.
Кажется, это не происходит со мной. Вот мой код:
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?
Если это так, то как вы должны загружать более сложный граф объектов такими отношениями?