Realm .NET 中的 LINQ 支持
要使用 Realm 进行查询,请使用Realm.All<T>()
方法获取IQueryable<T>
实例。 然后,您可以对此应用下面列出的操作符。
限制操作符
支持Where
。 OfType
不是,但它是多余的,因为 Realm 中的查询将始终由最初指定的类的集合组成。
Where
接受一个谓词。 要查看 Realm 查询中谓词支持的操作,请参阅谓词操作部分。
示例:
var oldDogs = realm.All<Dog>().Where(dog => dog.Age > 8);
排序操作符
OrderBy
、 OrderByDescending
、 Thenby
和ThenByDescending
均受支持。 尚不支持Reverse
。 目前,您只能按正在查询的类的持久属性进行排序。 这意味着尚不支持dogs.OrderBy(dog => dog.Owner.FirstName)
等。
示例:
var contacts = realm.All<Person>().OrderBy(p => p.LastName).ThenBy(p => p.FirstName);
转换操作符
ToArray
、 ToList
、 ToDictionary
和ToLookup
均受支持。 Cast
不是这样,但它是多余的,因为在Realm中的查询将始终由最初指定的类的collection组成。
示例:
var phoneBook = realm.All<Person>().ToDictionary(person => person.PhoneNumber);
元素操作符
支持所有主要元素操作符:
这些方法采用可选谓词。 要查看 Realm 查询中谓词支持的操作,请参阅谓词操作部分。
ElementAt
和ElementAtOrDefault
支持通过索引访问单个元素。
请注意,与默认(T)的标准 C 行为一样,如果没有匹配的元素,变体...OrDefault
会返回单个 null RealmObject
。
DefaultIfEmpty
尚不支持。
量词
Any
是支持的。
Any
接受一个可选谓词。 要查看 Realm 查询中谓词支持的操作,请参阅谓词操作部分。
聚合操作符
Count
是支持的。
尚不支持LongCount
、 Sum
、 Min
、 Max
和Average
。
Count
接受一个可选谓词。 要查看 Realm 查询中谓词支持的操作,请参阅谓词操作部分。
谓词操作
一般来说,您只能创建带有依赖于 Realm 中数据的条件的谓词。 想象一个类
class Person : RealmObject
{
// Persisted properties
public string FirstName { get; set; }
public string LastName { get; set; }
// Non-persisted property
public string FullName => FirstName + " " + LastName;
}
有了此类,您就可以使用适用于FirstName
和LastName
属性但不适用于FullName
属性的条件来创建查询。 同样,不能使用具有[Ignored]
属性的属性。
请注意,目前该属性必须位于条件的左侧。 这意味着
var oldDogs = realm.All<Dog>().Where(dog => 7 < dog.Age); // INVALID query, do not copy
是非法的,必须改为等效的
var oldDogs = realm.All<Dog>().Where(dog => dog.Age > 7); // Fixed
关系操作符
字符串操作符
对于字符串,可以使用: Contains
、 StartsWith
以及EndsWith
、 Equals
和Like
。
示例:
var peopleWhoseNameBeginsWithJ = realm.All<Person>.Where(p => p.FirstName.StartsWith("J"));
默认情况下,Realm 将执行区分大小写的比较,但您可以提供StringComparison.OrdinalIgnoreCase
参数来覆盖它。 由于在较旧的 .NET 框架上接受StringComparison
的Contains
没有重载,因此我们提供了一个可在查询时使用的辅助方法:
var peopleWhoseNameContainsA = realm.All<Person>().Where(p => QueryMethods.Contains(p.FirstName, "a", StringComparison.OrdinalIgnoreCase));
Like
查询方法可用于将字符串属性与模式进行比较。 ?
和*
可用作通配符,其中?
匹配 1 个字符, *
匹配 0 个或多个字符:
var words = realm.All<Word>().Where(p => QueryMethods.Like(p.Value, "?bc*"));
// Matches abc, cbcde, but not bcd
当不在查询表达式中使用时, Like
会转而使用 RegEx 来执行相同的规则。
组合
示例:
var PuppyRexes = realm.All<Dog>().Where(dog => dog.Age < 2 && dog.Name == "Rex");
关于活跃度的说明
Realm 查询是实时的,因为它们将继续代表数据库的当前状态。
realm.Write(() =>
{
realm.Add(new Person { FirstName = "John" });
realm.Add(new Person { FirstName = "Peter" });
});
var js = realm.All<Person>().Where(p => p.FirstName.StartsWith("J"));
foreach(var j in js)
{
Console.WriteLine(j.FirstName); // ==> John
}
realm.Write(() =>
{
realm.Add(new Person { FirstName = "Joe" });
});
foreach(var j in js)
{
Console.WriteLine(j.FirstName); // ==> John, Joe
}
这与对象/关系映射器 (ORM) 的典型行为不同,后者会获取查询结果并将其按原样保留在内存中。
但是,它也与 LINQ to Objects 的行为不同,在 LINQ to Objects 中,每次迭代都会重新评估表达式,这意味着条件两侧的更改都会影响结果。 Realm 查询将在首次运行时评估条件的右侧。 假设您有一个如下查询:
var recentLogEntries = realm.All<LogEntry>().Where(l => l.TimeStamp > DateTime.Now.AddHours(-1));
此处, recentLogEntries
变量将包含TimeStamp
晚于首次运行查询(通过foreach 、 ToList
等)时间前一小时的所有日志条目。 新添加的日志条目将包含在后续运行中,但它们的比较时间不会更新。
尚不支持
尚不支持以下功能。 其中一些将不受支持,因为 Realm 架构使它们变得不必要。
对操作符进行分组
GroupBy
不受支持。
设置操作符
不支持Distinct
、 Union
、 Intersect
和Except
。
分区操作符
尚不支持Take
、 Skip
、 TakeWhile
和SkipWhile
。
这些都没有使用 ORM 时那么重要。 鉴于 Realm 的零拷贝模式,只有在访问对象的属性时才会从数据库读取数据,因此简单地遍历结果的一部分几乎没有开销。
投影操作符
尚不支持Select
和SelectMany
。
只要您选择 RealmObject
本身而不是某些派生词,就支持与查询语法一起使用的 select 关键字:
var oldDogs = from d in realm.All<Dog>() where d.Age > 8 select d;
连接操作符
Concat
不受支持。
连接操作符
请注意,在使用 Realm 时,连接不如使用关系数据库和 ORM 时那么重要。 您无需使用键来标识关系,只需引用相关对象即可。
所以给定一个类
public class Address : RealmObject
{
public string StreetName { get; set; }
public int Number { get; set; }
}
你可以在另一个类中简单地使用它,如下所示:
public class Customer : RealmObject
{
public string Name { get; set; }
public Address Address { get; set; }
}
其工作方式类似于 C# 中的普通引用,这意味着如果为两个Customer
实例分配了相同的Address
对象,则对该地址的更改将应用于这两个客户对象。