Andrew_STOP_RU_WAR_IN_UA
Andrew_STOP_RU_WAR_IN_UA

Reputation: 11426

Query Realm for objects by IDs collection

is there exist any way to find list of objects by Id's collection ?

Sth like java's code:

realm.where(Foo.class).in("id", ids).findAll();

at the moment I have the following code:

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();
    }
}

but this still does'nt work because of ids.Contains(a.Id) is not supported by .Net Realm

Is there exist in c# any alternative of .in("id", ids) method?

Upvotes: 4

Views: 1030

Answers (1)

Andrew_STOP_RU_WAR_IN_UA
Andrew_STOP_RU_WAR_IN_UA

Reputation: 11426

I have resolved my problem after write of following extension:

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}'"));

            var rez = source.Filter(query);

            return rez;
        }

        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}"));

            var rez = source.Filter(query);

            return rez;
        }
    }
}

Such extension gave me ability to write the following:

public IQueryable<T> Get(List<string> ids, string idPropertyName = "Id")
{
    return _db.Realm.All<T>().In(idPropertyName,ids);
}



More complicated way, but works faster and better:

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);
    }
}

Example of usage:

_db.Realm.All<T>().In((a)=>a.Id, ids);

Upvotes: 6

Related Questions