Biarity/Sieve

Pass custom IQueryable to custom filter methods

anthonylevine opened this issue · 4 comments

I've got a unique situation in which I'd like to use Sieve with a custom join in EF core. I figured I could wrap the join and use the ToQueryable() to pass to Sieve. Unfortunately, it appears as though the custom filter methods try to create the IQueryable from the context which doesn't have a corresponding DBSet due to it being a join. Is there any way to work around this?

Can you share a sample? I couldn't understant what's your use case.

Sure, sorry.

I'd like to be able to filter on joined tables using sieve. Even something simple like this:

from category in categories join prod in products on category.ID equals prod.CategoryID select new { ProductName = prod.Name, Category = category.Name }; #

In theory, I could use this returned IQueryable and pass it to the SieverProcessor's Apply() method for paging and sorting. The issue becomes whenever I want to filter on this joined table. The custom filter methods are being called internally within Sieve (where Sieve is creating it's own IQueryable based on the type specified). This throws an error because there is no type on the DBSet (since it's a custom join). I believe this happens here: https://github.com/Biarity/Sieve/blob/master/Sieve/Services/SieveProcessor.cs#L443

Erm, no; Sieve is not creating its own IQueryable based on the type specified. It first searches for the name given. If it cannot find, it then searches for a signature match.

That being said; this type of usage actually conflicts with the core structure of the SieveProcessor. By design, the processor is expected to work with registered properties: with generic but strongly-typed entities, or with generic but strongly-typed custom methods. The canDo operations are tailored around that. It is possible to use weakly-typed entities but then you cannot use mapper.Property<OF> calls or [Sieve(CanDo = bool)] attributes. If you cannot use them then it is an open system to any IQueryable<T> and the benefits of property mapping and attribute decorating are voided. But, if you insist, you can try to implement a custom method, something like this:

IQueryable<T> CustomFilter<T>(IQueryable<T> source, string op, string[] values)

This is where you dont know which type to cast the source and do the filtering, T could be anything.

If you can introduce a type, say, SomeNewType,

from category in categories join prod in products on category.ID equals prod.CategoryID select new SomeNewType() { ProductName = prod.Name, Category = category.Name };

then you can both use attributes on properties of it, or registrations via mapper.Property<SomeNewType>(expression).

But again, the problem is still there. There's no set of SomeNewType in DBSet. Can you see where this is going? If there's no set facing the type you're working on it'll always fail nonetheless IF you route the filtering to the database.

You can also do this operations on the memory though.

Thanks for the reply.