Coder Social home page Coder Social logo

bcc-linq's People

Contributors

ketiovv avatar lcorneliussen avatar leo-schick avatar marioczyz avatar piotrczyz avatar rvanoord avatar u12206050 avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

bcc-linq's Issues

Add support for ThenInclude(...) on Enumerables

Currently .ThenInclude(...) only works after a non-enumerable object. Often it needs to be applied to an enumerable.

For example.

client.Persons.GetQueryable().Include(p => p.Affiliations).ThenInclude(a => a.Org)

Note that Affiliations in the example above is a List of affiliations.

Include and ThenInclude don't use JSON serialization settings when converting field to string

Example:

public class MyEntity
{
    [DataMember(Name = "other_entity")]
    [JsonProperty("other_entity")]
    public OtherEntity OtherEntity { get; set; }


 //...
}

...

var result = await client.MyEntities.Query().Include(e => e.OtherEntity).ToListAsync();


The above code results in fields=*,otherEntity.* in the query. The expected behaviour would be fields=*,other_entity.* if either DataMember or JsonProperty attributes are used with a name override.

The same applies to any query where the fields appear in the filter.

Nullable types

If you're filtering on a nullable type the the ApplyRuleFilter throws an exception:
Contributions.Contracts.Standard.Exceptions.ApiRequestException : Failed to retrieve data from /contributions/Projects?limit=100&page=1. Status code: BadRequest. Content: {"error":{"code":null,"message":"Expression of type 'System.Nullable1[System.DateTime]' cannot be used for parameter of type 'System.Object' of method 'Double ToDouble(System.Object)' (Parameter 'arg0')"},"errors":[]}

        {
            var filter = new Filter(jsonFilter);
            basicQuery = basicQuery.ApplyRuleFilter(filter);
        }```

Add extension function to apply IApiRequest on a IQueryable object

The current ApplyRuleFilter extension method makes it possible to apply a filter on IQueryable. But there are many other options like limit, offset, aggregte, sort, fields which we could apply to IQueryable.

I suggest to add a new IQueryable<TSource> ApplyApiRequest<TSource>(IApiRequest) which applies the IApiRequest properties Fields, Filter, Sort, Limit, Offset, Page, GroupBy, Deep and Alias in a single extension method. The IApiRequest properties Meta and Aggregate are not implemented by this.

Linq support for selecting Scalar

Linq queries selecting a scalar value are not possible. For example, calling

var query = from p in api.Persons
            select p.Age;

is not possible, but

var query = from p in api.Persons
            select new { p.Age };

is possible.

It is easy to use the workaround given above (introducing an anonymous type in the select clause), but this restriction does not allow us to use aggregat functions like this:

double averageAge = (
    from p in api.Persons
    select p.Age
).Average();

Server-side `ToString()` support in `filter` operations

Using ToString() in a filter` operation should be supported on server-side proprerties. Example:

var query =
    from p in api.Persons.AsQueryable()
    where p.Uid.ToString() == "70a10bd7-7912-4451-84e8-82ad45408c0c"
    select p;

Filter object for SDK Client

For Core API (api.bcc.no), we're using directus format for filtering and we send it as a query parameter to an endpoint like this:

 Task<CollectionResponse<ContributionRead>> Get(
        string jsonFilter,
        int pageNumber = 1,
        int itemsPerPage = 100,
        CancellationToken cancellationToken = default);

It doesn't make much sense using SDK Client if we need to still provide a json formatted string for filters. The idea is to create a C# implementation (Linq) that allows us to create a filter dynamically without taking care of validation of the filter.

How it could be used:

 var json = DirectusFilterBuilder<Project>.Create()
            .Where(x => x.Status == true)
            .Serialize();

We will focus on simple where operations:

  • Equal
  • GreaterThanOrEqual
  • LessThanOrEqual
  • GreaterThan
  • LessThan
  • IsTrue
  • IsFalse
  • operations for navigated properties
  • OR operations

RuleFilterParser handle int values in the filter

int, long, double values are always parsed as double, in the result it makes type mismatch with db entities.

Example RegistrationHours endpoint in Contribution API

Sending { "registrationId":{"_eq": 333755}} in the filter returns error because registrationId is type nullable Int32 but this value provided in the filter is always parsed to double

[Epic] Advanced Linq Queryable support

This is a collection ticket for improvements of the QueryProvider introduced via #20

Queryable Implementation matrix

When it is not implemented, the default behavior applies --> meaning: the query is performed on client side, possibly running heavy API loads against the API.

IQueryable function Implemented Unit tests exist
Aggregate No No
All No No
Any ✔️ #51 ✔️ #51
Append No No
Average ✔️ ⚠️ but cannot be used, see #26 and #27 No
Cast No No
Chunk No No
Concat No No
Contains No No
Count ✔️ ⚠️ but cannot be used, see #26 and #27 No
DefaultIfEmpty No No
Distinct No No
DistinctBy No No
ElementAt ✔️ #42 ✔️ #42
ElementAtOrDefault ✔️ #42 ✔️ #42
Except No No
ExceptBy No No
First ✔️ #42 ✔️ #42
FirstOrDefault ✔️ #42 ✔️ #42
GroupBy No No
GroupJoin No No
Intersect No No
IntersectBy No No
Join No No
Last No, require revert sorting No
LastOrDefault No, require revert sorting No
LongCount ✔️ ⚠️ but cannot be used, see #26 and #27 No
Max ✔️ ⚠️ but cannot be used, see #26 and #27 No
MaxBy No No
Min ✔️ ⚠️ but cannot be used, see #26 and #27 No
MinBy No No
OfType No No
Order No No
OrderBy ✔️ ✔️
OrderByDescending ✔️ ✔️
Prepend No No
Reverse No, easily possible No
Select ✔️ ✔️
SelectMany No No
SequenceEqual No No
SequenceEqual No No
Single ✔️ #42 ✔️ #42
SingleOrDefault ✔️ #42 ✔️ #42
Skip ✔️ ✔️ #30
SkipLast No, require revert sorting No, require revert sorting
SkipWhile No No
Sum ✔️ ⚠️ but cannot be used, see #26 and #27 No
Take ✔️ ✔️ #30
TakeLast No, require revert sorting No, require revert sorting
TakeWhile No No
ThenBy ✔️ ✔️
ThenByDescending ✔️ ✔️
Union No No
UnionBy No No
Where ✔️ ✔️
Zip No No

Other topics

IQueryable support

The package requires the ability to apply a rule filter on the IQueryable collection. At the moment it is only possible to use it on IEnumerable which is not enough if we want to handle database level filtering.

Linq Queryable support for selector parameter in aggregate functions

Linq brings multiple aggregate functions; Average, Count, LongCount, Max, Min, Sum

Currently it is not possible to use them. They are implemented without parameter, but cannot be used because of #26.

In addition, it would be great to have them implemented with parameter so that you can call them like this:

Call aggregation with property

double averageAge = api.Persons.Average(p => p.Age);

This option requires to have at least one row, otherwise Linq will crash because you cannot put null into double.

Call aggregation with property casted to null

double? averageAge = api.Persons.Average(p => (double?)p.Age);

This option will work when you have no row at all returning null.

Null checks in query don't result in expected JSON

Currently e.Parent.Id == null in a Linq query results in:

{ "parentId": { "_eq" : null }}

The expected directus-syntax is:

{ "parentId": { "_null" : true }}

for != null the expected syntax would be:

{ "parentId": { "_nnull" : true}}

Implement `ThenInclude`

With #37 we implement Include on just base level. Additional, we would like to add ThenInclude to define including/extending nested data from already nested data. e.g. api.Persons.Include(p => p.Car).ThenInclude(p.Manufacture)

This requires to implement interface IIncludableQueryable and return it in Include. This is required to implement ThenInclude.
The links refer to the EF Core implementation of such a logic.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.