odata.net
odata.net copied to clipboard
System.NotSupportedException: Could not convert constant System.Collections.Generic.List`1[System.Guid] expression to string
Hello.
I use Microsoft.OData.Client library to get data from service.
var dataServerUrl = "http://localhost:5005/api"; var oDataContext = new DataServiceContext(new Uri(dataServerUrl));
var dataSet4 = oDataContext.CreateQuery<JournalRecord>("JournalRecords");
var res43 = dataSet4.ToList(); var res441 = dataSet4.Where(i => res43.Any(db => db.ObjectId == i.ObjectId)).ToList();
or
var res43IdList = res43.Select(db => db.ObjectId).ToList();//.Take(100).ToList(); var res442 = dataSet4.Where(i => res43IdList.Contains(i.ObjectId)).ToList();
or
var res442 = dataSet4.Where(i => res43.Select(db => db.ObjectId).Any(i.ObjectId)).ToList();
I get error: "System.NotSupportedException: Could not convert constant System.Collections.Generic.List1[System.Guid] expression to string. at Microsoft.OData.Client.ExpressionWriter.VisitConstant(ConstantExpression c) at Microsoft.OData.Client.ALinqExpressionVisitor.Visit(Expression exp) at Microsoft.OData.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp) at Microsoft.OData.Client.ExpressionWriter.Visit(Expression exp) at Microsoft.OData.Client.ExpressionWriter.VisitMethodCall(MethodCallExpression m) at Microsoft.OData.Client.ALinqExpressionVisitor.Visit(Expression exp) at Microsoft.OData.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp) at Microsoft.OData.Client.ExpressionWriter.Visit(Expression exp) at Microsoft.OData.Client.ExpressionWriter.Translate(Expression e) at Microsoft.OData.Client.ExpressionWriter.ExpressionToString(DataServiceContext context, Expression e, Boolean inPath, Version& uriVersion) at Microsoft.OData.Client.UriWriter.VisitQueryOptions(ResourceExpression re) at Microsoft.OData.Client.UriWriter.VisitQueryableResourceExpression(QueryableResourceExpression rse) at Microsoft.OData.Client.DataServiceALinqExpressionVisitor.Visit(Expression exp) at Microsoft.OData.Client.UriWriter.Translate(DataServiceContext context, Boolean addTrailingParens, Expression e, Uri& uri, Version& version) at Microsoft.OData.Client.DataServiceQueryProvider.Translate(Expression e) at Microsoft.OData.Client.DataServiceQuery
1.Translate()
at Microsoft.OData.Client.DataServiceQuery1.Execute() at Microsoft.OData.Client.DataServiceQuery
1.GetEnumerator()
at System.Collections.Generic.List1..ctor(IEnumerable
1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at OdataToEntity.Test.DynamicDataContext.ODataClientTest.Controllers.TestController.GetByOData()"
What's wrong?
@ShvetsovAU Thank you for reporting this issue. I was able to reproduce it. Find my explanation below.
This is currently not supported:
var res43ObjectIdList = dataSet4.Select(d1 => d1.ObjectId).ToList();
System.NotSupportedException: 'Individual properties can only be selected from a single resource or as part of a type. Specify a key predicate to restrict the entity set to a single instance or project the property into a named or anonymous type.'
Workaround would be to do this:
// ?$select=ObjectId
var res43 = dataSet4.Select(d1 => new { d1.ObjectId }).ToList();
// Then generate an array of ObjectId
var res43IdList = res43.Select(d1 => d1.ObjectId).ToArray();
To achieve your objective, you could use the array in the code snippet above as follows:
// ?$filter=ObjectId in (...)
var res442 = dataSet4.Where(i => res43IdList.Contains(i.ObjectId)).ToList();
Support for IN with IEnumerable<T>
or arrays was introduced in this PR https://github.com/OData/odata.net/pull/1868. The Contains
method is translated to the in
expression. However, IList
/List
& ICollection
/Collection
are not currently supported. You can go through the conversation on the referenced PR for more details. We'd be appreciate a pull request contribution to add that support if you're in a position to. Kindly let me know if the workaround works for you
@ShvetsovAU Thank you for reporting this issue. I was able to reproduce it. Find my explanation below.
This is currently not supported:
var res43ObjectIdList = dataSet4.Select(d1 => d1.ObjectId).ToList();
System.NotSupportedException: 'Individual properties can only be selected from a single resource or as part of a type. Specify a key predicate to restrict the entity set to a single instance or project the property into a named or anonymous type.'
Workaround would be to do this:
// ?$select=ObjectId var res43 = dataSet4.Select(d1 => new { d1.ObjectId }).ToList(); // Then generate an array of ObjectId var res43IdList = res43.Select(d1 => d1.ObjectId).ToArray();
To achieve your objective, you could use the array in the code snippet above as follows:
// ?$filter=ObjectId in (...) var res442 = dataSet4.Where(i => res43IdList.Contains(i.ObjectId)).ToList();
Support for IN with
IEnumerable<T>
or arrays was introduced in this PR #1868. TheContains
method is translated to thein
expression. However,IList
/List
&ICollection
/Collection
are not currently supported. You can go through the conversation on the referenced PR for more details. We'd be appreciate a pull request contribution to add that support if you're in a position to. Kindly let me know if the workaround works for you
Hello.
Thank you for your answer.
Kindly let me know if the workaround works for you
Enough next:
var res43 = dataSet4.ToList();
var res43IdList = res43.Select(db => db.ObjectId).ToArray();//.ToList();; //TODO: IList/List & ICollection/Collection are not currently supported
var res442 = dataSet4.Where(i => res43IdList.Contains(i.ObjectId)).ToList();
@ShvetsovAU Thank you for reporting this issue. I was able to reproduce it. Find my explanation below.
Hello. Can you another check next issue https://github.com/OData/odata.net/issues/1247 ?