Столкнулся с проблемой. Есть решение моей проблемы для джавы:
realm.where(Foo.class).in("id", ids).findAll();
оно находит все элементы класса foo в базе данных которые входят в список айдишников ids
Мне пришлось написать костыль:
public interface IKeyedEntity
{
string Id { get; set; }
}
public class RealmServiceWrapper<T> where T: RealmObject, IKeyedEntity
{
public List<T> Get(List<string> ids)
{
return _db.Realm.All<T>().Where(a => ids.Contains(a.Id)).ToList();
}
}
Но он все равно не работает ибо с реалмом нельзя пользоватся конструкцией .Where(a => ids.Contains(a.Id))
:
System.NotSupportedException: 'The method 'Contains' is not supported'
Итак сам вопрос: есть ли альтернатива .in()
в шарпе?
По сути Where(a => ids.Contains(a.Id))
это то же самое, что и Where(a => a.Id == ids[0] || a.Id == ids[1] || ...)
, поэтому можно написать метод расширения, собирающий такое выражение "вручную":
public static class MyQueryableExtensions
{
public static IQueryable<T> In<T, TProp>(this IQueryable<T> source,
Expression<Func<T, TProp>> propSelector, IEnumerable<TProp> values)
{
var @params = propSelector.Parameters;
var propAcc = propSelector.Body;
Expression body = Expression.Constant(false, typeof(bool));
foreach (var v in values)
body = Expression.OrElse(body,
Expression.Equal(propAcc,
Expression.Constant(v, typeof(TProp))));
var lambda = Expression.Lambda<Func<T, bool>>(body, @params);
return source.Where(lambda);
}
}
Такой способ имеет несколько преимуществ перед заданием условия для фильтрации в виде строки: во-первых, не нужно тратить ресурсы на парсинг строки в дерево выражений, дерево у нас уже есть сразу, во-вторых, компилятор проверит, что такое свойство уже реально существует (не даст опечататься) и добавит типизации, т.е. не будет лишних упаковок/распаковок и бессмысленных сравнений строк с числами или т.п.
Пример использования:
_db.Realm.All<T>().In((a)=>a.Id, ids);
using Realms;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace ReLife.Services.RealmRelated.RealmExtensions
{
public static class IQueryableExtensions
{
public static IQueryable<T> In<T>(this IQueryable<T> source, string propertyName, List<string> objList) where T : RealmObject
{
var query = string.Join(" OR ", objList.Select(i => $"{propertyName} == '{i}'"));
return source.Filter(query);
}
public static IQueryable<T> In<T>(this IQueryable<T> source, string propertyName, List<int> objList) where T : RealmObject
{
var query = string.Join(" OR ", objList.Select(i => $"{propertyName} == {i}"));
return source.Filter(query);
}
}
}
Что дало мне возможность сделать вот так:
public IQueryable<T> Get(List<string> ids, string idPropertyName = "Id")
{
return _db.Realm.All<T>().In(idPropertyName,ids);
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
Есть скрипт Tile в котором находится метод ExplodeExternal() и есть ещё один скрипт Grid в котором хранится List minedTilesКак обратиться к членам minedTiles из скрипта...
В окне кнопка, у которой свойство IsEnabled должно быть true только если Text в TextBox соответствует паттерну RegexА в других случаях false