Reputation: 19
I've a parent class
public class Audit : BaseModel//Properties are intentionally made non virtual
{
public string Name { get; set; }
public int FacilityId { get; set; }
public string Passcode { get; set; }
public ICollection<AuditDate> AuditDates { get; set; }
}
and a child class
public class AuditDate : BaseModel
{
public int Duration { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate{ get; set; }
}
Now, these are used in entity framework (ver. 6) CF approach where
public virtual DbSet Audits { get; set; }
is declared. Then, I'm using below code to apply oData queries-
Prepared ODataQueryOptions:
private ODataQueryOptions PrepareOdataQueryOption(Uri oDataUri)
{
HttpConfiguration httpConfiguration = new HttpConfiguration();
httpConfiguration.EnableDependencyInjection();
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, oDataUri);
httpRequestMessage.Properties[HttpPropertyKeys.HttpConfigurationKey] = httpConfiguration;
ODataModelBuilder oDataModelBuilder = new ODataConventionModelBuilder();
oDataModelBuilder.EntityType<TDomainModel>();
ODataQueryContext oDataQueryContext = new ODataQueryContext(oDataModelBuilder.GetEdmModel(), typeof(TDomainModel), null);
return new ODataQueryOptions(oDataQueryContext, httpRequestMessage);
}
Apply ODataQueryOptions (dbSet is DbSet<T>, T is Audit in this case)
ODataQueryOptions oDataQueryOptions = PrepareOdataQueryOption(oDataUri);
IQueryable Value = oDataQueryOptions.ApplyTo(dbSet);
But when I call this using following oData uri
http://localhost:7071/api/Audit?$expand=AuditDates($filter=Id eq 1)
I get error at statement
IQueryable Value = oDataQueryOptions.ApplyTo(dbSet);
System.ArgumentNullException : Value cannot be null. Parameter name: type at Microsoft.OData.Edm.EdmUtil.CheckArgumentNull[T](T value,String parameterName). Microsoft.OData.Edm: Value cannot be null.
This happens only when I try to filter child records so that I can retrieve only few child records, not all.
Following URIs work as expected (error is only in case of filter on navigation properties):
Thanks!
Upvotes: 0
Views: 1233
Reputation: 19
The problem is in the following function (statement):
private ODataQueryOptions PrepareOdataQueryOption(Uri oDataUri)
{
...
oDataModelBuilder.EntityType<TDomainModel>();
...
}
Firstly, it should be EntitySet, not EntityType. EntitySet registers an entity set as a part of the model.
Secondly, as only parent object was declared, not navigation properties, it was unable to find the type of child records (hence, that error in "Parameter name: type").
I presumed that ODataModelbuilder will auto pick the AuditDate entity set (just like entity Framework Code First approach), but it didn't. I had to declare it explicitly. Thus, I changed above statement to the following statements (to match DbContext) and everything started working.
private ODataQueryOptions PrepareOdataQueryOption(Uri oDataUri)
{
...
oDataModelBuilder.EntitySet<Audit>("Audits");//Only parent domain model is required unless you want to filter navigation property rows
oDataModelBuilder.EntitySet<AuditDate>("AuditDates");
...
}
Upvotes: 0