Exception: System.NotSupportedException: Unable to create a constant value of type 'System.Object'. Only primitive types ('such as Int32, String, and Guid') are supported in this context. at System.Data.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.BinaryTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.UnarySequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.Convert()
at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
The method that the client invokes is the following:
public IList<DataContracts.TBL_Incident> GetIncidents(Guid? skipToken)
{
List<DataContracts.TBL_Incident> result = new List<DataContracts.TBL_Incident>();
ExceptionHandledOperation(delegate
{
using (IContextProxy context = _contextFactory.CreateObjectContext())
{
IQueryable<Domain.EntityModel.TBL_Incident> incidents;
if (!skipToken.HasValue)
{
incidents = (from i in context.TBL_Incident
orderby i.IncidentId
select i).Take(EntityModelServiceSettings.Current.EntitySetPageSize);
}
else
{
incidents = (from i in context.TBL_Incident
orderby i.IncidentId
where i.IncidentId.CompareTo(skipToken) > 0
select i).Take(EntityModelServiceSettings.Current.EntitySetPageSize);
}
foreach (var i in incidents)
{
#warning optimise generated method so that this can be done in less LOC
var mappedIncident = new DataContracts.TBL_Incident();
DataContracts.TBL_Incident.MapTBL_Incident(i, mappedIncident);
result.Add(mappedIncident);
}
}
});
return result;
}
The skipToken parameter allows the client to pass the last identifier from the previous page retrieved from the service.
sw.Start();
var incidents = client.GetIncidents(null);
Console.WriteLine("Set: {0} Time: {1}", incidents.Count(), sw.Elapsed);
incidents = client.GetIncidents(incidents.Last().IncidentId);
Console.WriteLine("Set: {0} Time: {1}", incidents.Count(), sw.Elapsed);
The cause of the exception is the service side statement that appends the skipToken to the query.
incidents = (from i in context.TBL_Incident
orderby i.IncidentId
where i.IncidentId.CompareTo(skipToken) > 0
select i).Take(EntityModelServiceSettings.Current.EntitySetPageSize);
The problem is that the compiler does not have a problem with the fact that the call passes the skipToken which is of type Nullable<Guid>. The problem is when the LINQ to Entity classes attempt to map the expression to a SQL expression.
To fix the problem it is simply a case of passing the skipToken.Value to the CompareTo() method.
incidents = (from i in context.TBL_Incident
orderby i.IncidentId
where i.IncidentId.CompareTo(skipToken.Value) > 0
select i).Take(EntityModelServiceSettings.Current.EntitySetPageSize);