【发布时间】:2019-01-02 22:08:22
【问题描述】:
我正在通过实现一个简单的财务簿记工具来试用 Realm。我正在使用类似于以下内容的架构(从基于 sql 的项目继承)
最初,我使用 long 类型的 PrimaryKey 为所有这些表设置类。然后我了解到,至少在 2015 年,领域doesn't support auto-increment。在我自己的测试中,这似乎是正确的,因为我收到一个异常说 0 是重复的主键。
查看getting started guide 上的示例,我试图重新评估我是否真的需要特定的 Id 字段。在大多数情况下,除了在数据库中使用主键的潜在速度优势之外,我似乎并没有特别做。但是,无论如何,当我建立关系时,期望 Realm 在后台执行此操作对我来说似乎是合理的。不过有一个例外。
// TransactionLink.cs
using Realms;
namespace Finance.Models {
public class TransactionLink : RealmObject {
public Transaction Lhs { get; set; }
public Transaction Rhs { get; set; }
}
}
// Transaction.cs
using Realms;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Finance.Models {
public class Transaction : RealmObject {
[PrimaryKey]
public long Id { get; set; }
// ...
[Ignored]
public IQueryable<Transaction> LinkedTransactions {
get {
var lhs = Realm.All<TransactionLink>().Where(tl => tl.Lhs.Id == Id).Select(tl => tl.Rhs);
var rhs = Realm.All<TransactionLink>().Where(tl => tl.Rhs.Id == Id).Select(tl => tl.Lhs);
return lhs.Union(rhs);
}
}
}
}
起初,我考虑让 Transaction 有一个字段 IList<Transaction>,但我不喜欢删除一个条目将其添加到它们两者的好处。必须维护数据的单独副本对我没有吸引力。我考虑过使用Equals 函数比较Id 而不是因为我注意到RealmObject 重载它(类似于tl => tl.Rhs.Equals(this)),但我不确定它在查询中的处理方式(也许我应该在发布后尝试问题...但我距离能够测试它还有一点距离)
好吧,在这一点上(我可能是错的)似乎对我来说最好实现一些自动递增的东西。因此,按照afore-mentioned stack overflow post 中的示例,我想出了一些东西。
// IPrimaryKeyId.cs
namespace Finance.Context {
public interface IPrimaryKeyId {
long Id { get; set; }
}
}
// Database.cs
using Finance.Models;
using Realms;
using System.Linq;
using System.Windows;
using static Finance.Context.Handle;
namespace Finance.Context {
public class Database {
//-------------------------------------------------------------------------------------------------------------+
// Non-Static Interface: Provide access to all the tables in the database |
//-------------------------------------------------------------------------------------------------------------+
private Realm Db { get; set; }
public IQueryable<Bank> Banks { get { return Db.All<Bank>(); } }
public IQueryable<Models.Transaction> Transactions { get { return Db.All<Models.Transaction>(); } }
public IQueryable<TransactionLink> TransactionLinks { get { return Db.All<TransactionLink>(); } }
// ...
public void SetupExample() {
AutoIncrement(new Bank { Name = "Cash" });
var first = Banks.First();
MessageBox.Show(first.Id.ToString() + ": " + first.Name);
}
public void AutoIncrement<T>(T obj) where T : RealmObject, IPrimaryKeyId {
AutoIncrement(Db, obj);
}
public static void AutoIncrement<T>(Realm db, T obj) where T : RealmObject, IPrimaryKeyId {
db.Write(() => {
long id = db.All<T>().Max(el => el.Id);
obj.Id = id + 1;
db.Add(obj);
});
}
}
}
afore-mentioned guide 表示领域不喜欢这些类中的继承,但使用这个简单的接口似乎可以正常运行。问题是在调用Max() 的行上会抛出NotSupportedException。所以现在我还有一些潜在的问题需要解决,其中任何一个都会让我继续前进。
- 替代
Max()用于确定最大值Id - 验证在 Linq 查询中使用
Equals(this)并同时放弃 Id 的效果 - 我没有考虑过的另一种选择
这是为了让我习惯于境界,所以我想尽可能地以“境界方式”做事。欢迎任何其他关于我如何更好地适应这种风格的方法。
对@Cristo 的回应
调用异常的行是long id = db.All<T>().Max(el => el.Id);,正如您在上面的代码sn-p中看到的那样。确切的文本是System.NotSupportedException: 'The method 'Max' is not supported'。堆栈跟踪是
[External Code]
Finance.exe!Finance.Context.Database.AutoIncrement.AnonymousMethod__0() Line 48 C#
[External Code]
Finance.exe!Finance.Context.Database.AutoIncrement<Finance.Context.Handle>(Realms.Realm db, Finance.Context.Handle obj) Line 47 C#
Finance.exe!Finance.Context.Database.Create(string file) Line 74 C#
Finance.exe!Finance.MainWindow.Button_Click(object sender, System.Windows.RoutedEventArgs e) Line 14 C#
[External Code]
其中第 47 行对应于db.Write(,第 48 行对应于调用Max 的行
【问题讨论】:
-
github.com/realm/realm-dotnet/issues/new "我们监控
realm标签。" - 那你在哪里?....