Reputation: 73
I am trying to implement querying to Sql Server via EF Core and OData(7.1.0).
Action method looks like follows:
[HttpGet]
public IEnumerable<UserInfoDto> Get(ODataQueryOptions ops)
{
return this.service.GetUserInfos(ops);
}
Service code:
public List<UserInfoDto> GetUserInfos(ODataQueryOptions ops)
{
using (var context = new EFContext())
{
var query = context.Users.Join(context.Customers, x => x.CustomerId, y => y.Id, (x, y) => new UserInfoDto
{
Id = x.Id,
Name = x.Name,
Age = x.Age,
CustomerId = x.CustomerId,
CustomerTitle = y.Title,
CustomerDescription = y.Description
});
var result = ops.ApplyTo(query).Cast<UserInfoDto>().ToList();
return result;
}
}
Startup Configute
method:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMvc(b =>
{
b.Count().Filter().OrderBy().Select().MaxTop(null);
b.EnableDependencyInjection();
});
}
However, when I am having $select
in query (e.g https://localhost:5001/api/userinfos?$select=id), instead of projected result I am getting an error:
InvalidOperationException: No coercion operator is defined between types 'Microsoft.AspNet.OData.Query.Expressions.SelectExpandBinder+SelectSome`1[Oda taApp.UserInfoDto]' and 'OdataApp.UserInfoDto'.
What am I missing? Any help is appreciated.
Upvotes: 4
Views: 3814
Reputation: 461
When you using $select
query option for OData, you need an IQueryable of dynamic
.
For example, imagine the following class:
public class Person {
public int Id { get; set }
public string Name { get; set; }
}
So, if you have a query without $select
, the IQueryable will generate a collection of Person, with all properties (id and name) in each item.
But, if you use a $select=id
query, each item will have only the ID property and you cant Cast a dynamic type to a Person type.
In other words, you cant use $select
and return a List<UserInfoDto>
, you need to return a List<dynamic>
without the Cast method, just like this:
var result = ops.ApplyTo(query) as IQueryable<dynamic>;
return result.ToList();
EDIT:
the full implementation of method will be:
// changing the return type
public List<dynamic> GetUserInfos(ODataQueryOptions<UserInfoDto> ops)
{
using (var context = new EFContext())
{
var query = context.Users.Include(Customers, x => x.CustomerId, y => y.Id, (x, y) => new UserInfoDto
{
Id = x.Id,
Name = x.Name,
Age = x.Age,
CustomerId = x.CustomerId,
CustomerTitle = y.Title,
CustomerDescription = y.Description
});
// casting the applyto result
var result = ops.ApplyTo(query) as IQueryable<dynamic>;
return result.ToList();
}
}
Upvotes: 3