我正在编写一个在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:不支持方法'Any' 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):在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):在Realms.ExpressionVisitor.Visit(System.Linq.Expressions.Expression exp)[0x000ec] in:0 06-07 15:04:55.097 I / MonoDroid(24526):at Realms.RealmResults
1[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]在/ Users / builder /数据/通道/ 3053 / a94a03b5 /源/单声道/外部/ referencesource / System.Core程序/系统/ LINQ的/ Enumerable.cs:835 06-07 15:04:55.098 I / MonoDroid(24526):在d:\ rwagh \ mediq \ Code \ VHS中的VHS.MobileApp.Mediq.DataAccess.ObservationDatabase +&lt;&gt; c__DisplayClass13.b__8()[0x00147]。 MobileApp.Mediq.DataAccess \ ObservationDatabase.cs:65 06-07 15:04:55.098 I / MonoDroid(24526):在/ Users / builder / data / lanes / 3053中的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] /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 = observations.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)) { ...
但这也不起作用。
答案 0 :(得分:4)
Realm支持LINQ - 我们解析表达式树(好的,有些位丢失,但基础知识在那里,我们会定期改进 - 我们将添加包含)。
因此,只要您需要在运行时构建完全任意的查询表达式,就可以使用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}");
}
}