c# - Applying Distinct to OData query -


i want list of distinct values odata endpoint. distinct or group isn't supported yet.

my uri query looks this

get /odata/products?$select=foo & $top=10 & $count=true & distinct=true 

my controller

[enablequery] public iqueryable<foobarbaz> get(odataqueryoptions<foobarbaz> queryoptions, bool distinct) {         //i've tried following         return repository.asqueryable().distinct();          // ,         return repository.asqueryable().groupby(x => x.foo);          // ,         iqueryable query = queryoptions.applyto(repository.asqueryable());         return query.distinct(); // can't call .distinct() here } 

none work :(

the best solution solve problem defining collection action on resource.

first step : configure 'distinct' action in webapiconfig.cs

odataconventionmodelbuilder builder = new odataconventionmodelbuilder(); builder.entityset<foobarbaz>("foobarbazs");//resource name  actionconfiguration distinct = builder.entity<foobarbaz>().collection.action("distinct");//name of action method distinct.returnscollectionfromentityset<foobarbaz>("foobarbazs");//return type of action distinct.parameter<string>("on");//property on collection filtered distinct  config.routes.mapodataroute("odata", "odata", builder.getedmmodel()); 

second step : add action in foobarbazscontroller.cs returns collection of distinct entities

[enablequery]//enable $select,$expend queries [httppost]//all action methods of post type in web api public iqueryable<foobarbaz> distinct(odataactionparameters parameters) {         string on = "";         if (!modelstate.isvalid)         {             throw new httpresponseexception(httpstatuscode.badrequest);         }          try         {              on = parameters["on"] string;         }         catch (nullreferenceexception ex)         {             httpresponsemessage message = new httpresponsemessage(httpstatuscode.badrequest);             message.content = new stringcontent("{\"error\":\"invalid query -> on property not defined\"}");             throw new httpresponseexception(message);         }         catch (exception ex)         {             throw new httpresponseexception(httpstatuscode.badrequest);         }           propertyinfo[] props = new foobarbaz().gettype().getproperties(bindingflags.public | bindingflags.instance);         var ispropertyexist = false;         (int = 0; < props.length; i++)         {             if (props[i].name.equals(on))             {                 ispropertyexist = true;                 break;             }         }           if (ispropertyexist)         {             var foobarbazcollection = db.foobarbazs.groupby(getgroupkey(on)).select(g => g.firstordefault());//select distinct entity on basis of property             return foobarbazcollection ;         }         else         {             httpresponsemessage message = new httpresponsemessage(httpstatuscode.badrequest);             message.content = new stringcontent("{\"error\":\"property '"+on+"' not exist}");             throw new httpresponseexception(message);         } } 

third step : add static method returns expression groupby on basis of property name.

private static expression<func<foobarbaz, string>> getgroupkey(string property)     {         var parameter = expression.parameter(typeof(foobarbaz));         var body = expression.property(parameter, property);         return expression.lambda<func<foobarbaz, string>>(body, parameter);     }  

now build project , can query resource this

post /odata/foobarbazs/distinct http/1.1 host: localhost:9360 content-type: application/json cache-control: no-cache postman-token: 6d174086-7b97-76a2-679c-4dab3dfb5938  {"on":"propertyname"}  

and can use $select , $expend this

post /odata/foobarbazs/distinct?$select=propertyname1,propertyname2 http/1.1 host: localhost:9360 content-type: application/json cache-control: no-cache postman-token: 6d174086-7b97-76a2-679c-4dab3dfb5938  {"on":"propertyname"}  

i hope solve problem. +1 if do.


Comments