c# – realm.xamarin抛出错误:不支持方法’Contains’. ‘任意’相同

我正在编写一个查询,它需要在realm.xamarin linq查询中使用’WHERE IN’like子句.下面是我试过的查询:

var IdsToMatch = observations.Select(x => x.Id)
var results = from d in realm.All<Observations>() where IdsToMatch.Any(p => p == d.Id) select d;

还尝试使用Contains:

var results = from d in realm.All<Observations>() where IdsToMatch.Contains(d.Id) select d;

但这会引发错误:

The method 'Contains' is not supported
The method 'Any' is not supported

这是什么解决方案?

编辑:

这是错误的堆栈跟踪:

UNHANDLED EXCEPTION:
06-07 15:04:55.097 I/MonoDroid(24526): System.NotSupportedException: The method ‘Any’ is not supported
06-07 15:04:55.097 I/MonoDroid(24526): at Realms.RealmResultsVisitor.VisitMethodCall (System.Linq.Expressions.MethodCallExpression m) [0x00596] in :0
06-07 15:04:55.097 I/MonoDroid(24526): at Realms.ExpressionVisitor.Visit (System.Linq.Expressions.Expression exp) [0x000ec] in :0
06-07 15:04:55.097 I/MonoDroid(24526): at Realms.RealmResultsVisitor.VisitMethodCall (System.Linq.Expressions.MethodCallExpression m) [0x0006a] in :0
06-07 15:04:55.097 I/MonoDroid(24526): at Realms.ExpressionVisitor.Visit (System.Linq.Expressions.Expression exp) [0x000ec] in :0
06-07 15:04:55.097 I/MonoDroid(24526): at Realms.RealmResults1[T].CreateResultsHandle () [0x00037] in <filename unknown>:0
06-07 15:04:55.097 I/MonoDroid(24526): at Realms.RealmResults
1[T].get_ResultsHandle () [0x0000d] in :0
06-07 15:04:55.097 I/MonoDroid(24526): at Realms.RealmResults1[T].GetEnumerator () [0x00000] in <filename unknown>:0
06-07 15:04:55.097 I/MonoDroid(24526): at System.Collections.Generic.List
1[T]..ctor (IEnumerable1 collection) [0x00073] in /Users/builder/data/lanes/3053/a94a03b5/source/mono/external/referencesource/mscorlib/system/collections/generic/list.cs:104
06-07 15:04:55.098 I/MonoDroid(24526): at System.Linq.Enumerable.ToList[TSource] (IEnumerable
1 source) [0x00011] in /Users/builder/data/lanes/3053/a94a03b5/source/mono/external/referencesource/System.Core/System/Linq/Enumerable.cs:835
06-07 15:04:55.098 I/MonoDroid(24526): at VHS.MobileApp.Mediq.DataAccess.ObservationDatabase+<>c__DisplayClass13.b__8 () [0x00147] in d:\rwagh\mediq\Code\VHS.MobileApp.Mediq.DataAccess\ObservationDatabase.cs:65
06-07 15:04:55.098 I/MonoDroid(24526): at System.Threading.Tasks.Task1[TResult].InnerInvoke () [0x00012] in /Users/builder/data/lanes/3053/a94a03b5/source/mono/external/referencesource/mscorlib/system/threading/Tasks/Future.cs:686
06-07 15:04:55.098 I/MonoDroid(24526): at System.Threading.Tasks.Task.Execute () [0x00016] in /Users/builder/data/lanes/3053/a94a03b5/source/mono/external/referencesource/mscorlib/system/threading/Tasks/Task.cs:2523
06-07 15:04:55.098 I/MonoDroid(24526): --- End of stack trace from previous location where exception was thrown ---
06-07 15:04:55.098 I/MonoDroid(24526): at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/3053/a94a03b5/source/mono/external/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143
06-07 15:04:55.098 I/MonoDroid(24526): at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) [0x00047] in /Users/builder/data/lanes/3053/a94a03b5/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:201
06-07 15:04:55.098 I/MonoDroid(24526): at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) [0x0002e] in /Users/builder/data/lanes/3053/a94a03b5/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:170
06-07 15:04:55.098 I/MonoDroid(24526): at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) [0x0000b] in /Users/builder/data/lanes/3053/a94a03b5/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:142
06-07 15:04:55.098 I/MonoDroid(24526): at System.Runtime.CompilerServices.TaskAwaiter
1[TResult].GetResult () [0x00000] in /Users/builder/data/lanes/3053/a94a03b5/source/mono/external/referencesource/mscorlib/system/runtime/compilerservices/TaskAwaiter.cs:372

编辑2:

var IdsToMatch = observations.Select(x => x.Id)
var results = from d in realm.All<Observations>() where IdsToMatch.Any(p => p == d.Id) select d;

尝试过:var IdsToMatch = observation.Select(x => x.Id).AsQueryable()
按照https://github.com/realm/realm-dotnet/blob/7187390529201ba843cd105fc6e3e11acb0c6217/Realm.Shared/linq/RealmResultsVisitor.cs#L121说的那样

internal override Expression VisitMethodCall(MethodCallExpression m)
        {
            if (m.Method.DeclaringType == typeof(Queryable)) { ...

但那也行不通.

解决方法:

好的,这很有趣.答案(现在)是建立一个LINQ Expression Tree.

Realm支持LINQ – 我们解析表达式树(好的,有些位丢失,但基础知识在那里,我们正在定期改进 – 我们将添加Contains).

因此,只要您需要在运行时构建完全任意的查询表达式,就可以使用LINQ的强大功能.

下面的示例可能看起来有点复杂,但关键是它使用标准的表达式树,因此您可以使用构建此类树的任何其他代码.

class HasIntKey : RealmObject {
    public int UserKey { get; set; }
}


private void FindingManyMatches()
{
    using (var theRealm = Realm.GetInstance ("TestingManyKeys.realm")) {
        // create some sample data
        theRealm.Write (() => {
            for (int i = 1; i < 10000; i++) {
                var obj = theRealm.CreateObject<HasIntKey> ();
                obj.UserKey = i;
            }
        });
        var allInts = theRealm.All<HasIntKey>();
        Console.WriteLine ($"Created {allInts.Count()} objects");

        var idsToMatch = new[] {42,1003,400,57, 6009};

        // technique for how to search for many matches
        // use Expression Trees to dynamically build the LINQ statement
        // see https://msdn.microsoft.com/en-us/library/mt654267.aspx
        ParameterExpression pe = Expression.Parameter (typeof(HasIntKey), "p");

        // building an expression like:
        // allInts.Where (p => p.UserKey == idsToMatch[0] || p.UserKey == idsToMatch[1]...);
        Expression chainedByOr = null;
        // left side of the == will be the same for each clause we add in the loop
        Expression left = Expression.Property(pe, typeof(HasIntKey).GetProperty("UserKey"));  
        foreach (int anId in idsToMatch) {
            // Create an expression tree that represents the expression 'p.UserKey == idsToMatch[n]'.
            Expression right = Expression.Constant(anId);
            Expression anotherEqual = Expression.Equal(left, right);
            if (chainedByOr == null)
                chainedByOr = anotherEqual;
            else 
                chainedByOr = Expression.OrElse (chainedByOr, anotherEqual);
        }
        MethodCallExpression whereCallExpression = Expression.Call(
            typeof(Queryable),
            "Where",
            new Type[] { allInts.ElementType },
            allInts.Expression,
            Expression.Lambda<Func<HasIntKey, bool>>(chainedByOr, new ParameterExpression[] { pe }));

        // Create an executable query from the expression tree.
        IQueryable<HasIntKey> results = allInts.Provider.CreateQuery<HasIntKey>(whereCallExpression);

        // now we have our results, display some details!
        Console.WriteLine ($"Found {results.Count()} objects");

        // Enumerate the results.
        foreach (HasIntKey anObj in results)
            Console.WriteLine($"Found key {anObj.UserKey}");
    }
}
上一篇:Realm.io – 在Android之外使用(在Java中)


下一篇:如果在没有关闭开放领域实例的情况下关闭我的Android应用程序会发生什么?