境界.NET带有Contains()的Where查询抛出System.NotSupportedException



我正在使用Realm。NET v10.1.3,我有一个删除一些对象的方法。从表明支持Contains的文档中提取,我有以下片段:

var results = realm.All<DeviceEventEntity>()
.Where(entity => ids.Contains(entity.Id));

realm.RemoveRange(results);

但当执行realm.RemoveRange(results)时,Realm抛出一个系统。NotSupportedException。我在这里做错了什么?或者Realm不支持Contains?

这是堆叠竞赛:

System.NotSupportedException
The method 'Contains' is not supported
at Realms.RealmResultsVisitor.VisitMethodCall(MethodCallExpression node) in C:jenkinsworkspacerealm_realm-dotnet_PR-2362@2RealmRealmLinqRealmResultsVisitor.cs:line 378
at Realms.RealmResultsVisitor.VisitMethodCall(MethodCallExpression node) in C:jenkinsworkspacerealm_realm-dotnet_PR-2362@2RealmRealmLinqRealmResultsVisitor.cs:line 164
at Realms.RealmResults`1.CreateHandle() in C:jenkinsworkspacerealm_realm-dotnet_PR-2362@2RealmRealmLinqRealmResults.cs:line 65
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at Realms.RealmResults`1.get_ResultsHandle() in C:jenkinsworkspacerealm_realm-dotnet_PR-2362@2RealmRealmLinqRealmResults.cs:line 30
at Realms.Realm.RemoveRange[T](IQueryable`1 range) in C:jenkinsworkspacerealm_realm-dotnet_PR-2362@2RealmRealmRealm.cs:line 1279
at DocLink.Client.Storage.Service.Event.DeviceEventService.<>c__DisplayClass2_0.<DeleteEvents>b__0() in

这里有一个更完整的例子:

public Task DeleteEvents(List<ObjectId> ids) {
return Task.Run(() => {
using (var realm = GetRealm()) {
using (var transaction = realm.BeginWrite()) {
try {
var results = realm.All<DeviceEventEntity>().Where(entity => ids.Contains(entity.Id));
realm.RemoveRange(results);
transaction.Commit();
}
catch (Exception exception) {
transaction.Rollback();
throw new ServiceException("Unable to delete events. Transaction has been rolled back.", exception);
}
}
}
});
}

此外,库引用像C:jenkinsworkspacerealm_realm-dotnet_PR-2362@2RealmRealmLinqRealmResultsVisitor.cs这样的文件似乎有点奇怪。这不是我系统中的任何内容,库是通过NuGet获取的。

文档表示,遇到NotSupportedException时需要使用Filter。阅读关于NSPredicate备忘单链接方法的评论,你可以用它做很多事情:(

更新到问题。首先,感谢所有参与并帮助我指明正确方向的人。最终的答案是几件事的结合,但简而言之,正是前一篇文章最终解决了这个问题。

Realm的当前版本支持MongoObjectId,但是在Filter((方法中使用ObjectId并不能真正起作用。因此,修复方法是最终使用字符串作为PK,但在DTO中使用ObjectId——在退出时转换为ObjectId,在进入Realm时转换为ToString((。

public static class IQueryableExtensions {
public static IQueryable<T> In<T>(this IQueryable<T> source, string propertyName, IList<ObjectId> objList)
where T : RealmObject {
var query = string.Join(" OR ", objList.Select(i => $"{propertyName} == '{i.ToString()}'"));
var results = source.Filter(query);
return results;
}
}

我的代码使用扩展

public Task DeleteEvents(List<ObjectId> ids) {
return Task.Run(() => {
using (var realm = GetRealm())
{
using (var transaction = realm.BeginWrite())
{
try {
// In order to support this with the current version of Realm we had to write an extension In()
// that explodes the list into a Filter() expression of OR comparisons. This also required us
// to use string as the underlying PK type instead of ObjectId. In this way, our domain object
// still expects ObjectId, so we ToString() on the way into realm and ObjectId.Parse() on the
// way out to our DTO.
var results = realm.All<DeviceEventEntity>().In("Id", ids);
realm.RemoveRange(results);
transaction.Commit();
}
catch (Exception exception)
{
transaction.Rollback();
throw new ServiceException("Unable to delete events. Transaction has been rolled back.", exception);
}
}
}
});
}

此版本适用于guid属性

public static IQueryable<T> In<T>(this IQueryable<T> source, string propertyName, IEnumerable<Guid?> objList)
where T : IRealmObject
{
int count = 0;
var query = string.Concat("Id in { $", string.Join(", $", objList.Select(i => count++)), "}");
var results = source.Filter<T>(query, objList.Select(x=> (QueryArgument)x).ToArray());
return results;
}

相关内容

最新更新