具有复杂类型的WebApi OData查询忽略嵌套值

时间:2016-07-13 10:21:53

标签: entity-framework asp.net-web-api odata

使用Entity Framework我创建了一个DbContext。 Dbcontext是在WebApi项目中创建的。 DbContext中的一个表代表建筑物。该位置在数据库中表示为Geography类型。我需要查询建筑物并按照到给定位置的距离对结果进行排序。

用于查询的类型是

[DataContract]
public class BuildingDistance
{
    [Key]
    [DataMember]
    public string Id { get; set; }
    [DataMember]
    public string Street { get; set; }
    [DataMember]
    public double? Distance { get; set; }
    [DataMember]
    public t_building Building { get; set; }
}

此类型已在modelbuilder中注册

ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
// ... Registration of the types generated by EF
builder.EntitySet<t_building>("t_building");
builder.EntitySet<BuildingDistance>("BuildingDistances");

我定义了以下控制器操作

        public IHttpActionResult GetBuildingDistances(ODataQueryOptions<BuildingDistance> queryOptions)
    {
        // validate the query.
        try
        {
            queryOptions.Validate(_validationSettings);
        }
        catch (ODataException ex)
        {
            return BadRequest(ex.Message);
        }

        dbcontext db = new dataBaseEntities();
        string pointString = string.Format(CultureInfo.InvariantCulture.NumberFormat, "POINT({0} {1})", 11.53128, 48.17883);
        DbGeography myLocation = DbGeography.FromText(pointString, 4326);
        var query =
            db.t_building.Select(
                x =>
                    new BuildingDistance
                    {
                        Id = x.id,
                        Street = x.location_street,
                        Building = x,
                        Distance = x.GeoLocation.Distance(myLocation)
                    });

        var result = queryOptions.ApplyTo(query) as IQueryable<BuildingDistance>;

        return Ok(result);
    }

执行查询并将结果发送到客户端。问题是缺少建筑属性

{  "odata.metadata":"http://localhost:50732/odata/$metadata#BuildingDistances","value":[
{
  "Id":"15FF94FE-3CB8-4CF6-BE89-501A8366ED7C","Strasse":"Maistr.","Distance":4407.0418114105069
}  ]

}

实际上只填充了属性ID,距离和街道。酒店大楼被遗漏了。

如果我在LinqPad中运行此查询,则会填充属性Building。

属性不是只读的,因此排除here的情况。

感谢您的任何建议!

更新:尝试了范欧阳推荐的方法,我收到以下错误

  

&#39; ObjectContent`1&#39;类型无法序列化响应正文   内容类型&#39; application / json;字符集= UTF-8&#39;

更新:尝试使用属性ForeignKey使用OData的导航属性方法。没有运气,有无扩张。

1 个答案:

答案 0 :(得分:0)

你应该

$expand=Building 

在查询中,在有效负载中包含导航属性。

当查询中有$ expand或$ select时,applyto方法的结果类型将是WebAPI / OData中的包装类,因此您应该删除as IQueryable<BuildingDistance>并使用{{3}之类的代码}

或者您可以在控制器方法中使用EnableQuery Attribute并返回查询:

[EnableQuery]
public IHttpActionResult GetBuildingDistances()
{
    ...
    var query =
        db.t_building.Select(
            x =>
                new BuildingDistance
                {
                    Id = x.id,
                    Street = x.location_street,
                    Building = x,
                    Distance = x.GeoLocation.Distance(myLocation)
                });
    return Ok(query as IQueryable<BuildingDistance);
}