【问题标题】:automatically expand related entity with OData controller使用 OData 控制器自动展开相关实体
【发布时间】:2017-09-01 14:35:10
【问题描述】:

我有这些课程:

    public class Items
    {
    [Key]
    public Guid Id { get; set; }
    public string ItemCode { get; set; }
    public decimal SalesPriceExcl { get; set; }
    public decimal SalesPriceIncl { get; set; }

    public virtual ICollection<ItemPrice> SalesPrices { get; set; }

    public Items()
    {
        SalesPrices = new HashSet<App4Sales_ItemPrice>();
    }
}

 public class ItemPrice
{
    [Key, Column(Order = 0), ForeignKey("Items")]
    public Guid Id { get; set; }
    public virtual Items Items { get; set; }

    [Key, Column(Order=1)]
    public Guid PriceList { get; set; }        
    public decimal PriceExcl { get; set; }
    public decimal PriceIncl { get; set; }
    public decimal VatPercentage { get; set; }        

}

我想查询 Items 并自动获取 ItemPrice 集合。

我创建了一个 OData V3 控制器:

    // GET: odata/Items
    //[Queryable]
    public IQueryable<Items> GetItems(ODataQueryOptions opts)
    {
        SelectExpandQueryOption expandOpts = new SelectExpandQueryOption(null, "SalesPrices", opts.Context);
        Request.SetSelectExpandClause(expandOpts.SelectExpandClause);
        return expandOpts.ApplyTo(db.Items.AsQueryable(), new ODataQuerySettings()) as IQueryable<Items>;


    }

但我得到了错误: “无法序列化空提要”

是的,有些商品没有 ItemPrice 清单。

我可以克服这个错误,还是可以做一些不同的事情?

亲切的问候

杰伦

我发现潜在的错误是: 无法转换类型的对象 'System.Data.Entity.Infrastructure.DbQuery1[System.Web.Http.OData.Query.Expressions.SelectExpandBinder+SelectAllAndExpand1[.Models.Items]]' 输入“.Models.Items”。

【问题讨论】:

    标签: asp.net-web-api2 odata


    【解决方案1】:

    在上面https://stackoverflow.com/a/43339286/507421 并添加一种获取选择和扩展属性的方法

    public static IQueryable<T> ApplyODataOptions<T>(this IQueryable<T> query, ODataQueryOptions options) where T : new()
    {
        if (options == null)
        {
            return query;
        }
    
        var queryable = options.ApplyTo(query);
        if (queryable is IQueryable<T> queriableEntity)
        {
            return queriableEntity;
        }
        var results = new List<T>();
        foreach (var item in queryable)
        {
            var instanceProp = item.GetType().GetProperty("Instance");
            var value = (T)instanceProp.GetValue(item) ?? new T();
            results.Add(value);
    
            var containerProp = item.GetType().GetProperty("Container");
            var container = containerProp.GetValue(item);
            while (container != null)
            {
                var containerType = container.GetType();
                var containerValue = containerType.GetProperty("Value").GetValue(container);
                var containerName = containerType.GetProperty("Name").GetValue(container) as string;
                var expandedProp = typeof(T).GetProperty(containerName);
                if (containerValue is IEnumerable containerValues)
                {
                    var listType = typeof(List<>).MakeGenericType(expandedProp.PropertyType.GenericTypeArguments[0]);
                    var expandedList = (IList)Activator.CreateInstance(listType);
                    foreach (var expandedItem in containerValues)
                    {
                        var expandedInstanceProp = expandedItem.GetType().GetProperty("Instance");
                        var expandedValue = expandedInstanceProp.GetValue(expandedItem);
                        expandedList.Add(expandedValue);
                    }
                    expandedProp.SetValue(value, expandedList);
                }
                else
                {
                    expandedProp.SetValue(value, containerValue);
                }
                container = containerType.GetProperty("Next0")?.GetValue(container);
            }
        }
        return results.AsQueryable<T>();
    }
    

    【讨论】:

      【解决方案2】:

      我在看到这个帖子后解决了这个问题:http://www.jauernig-it.de/intercepting-and-post-processing-odata-queries-on-the-server/

      这是我现在的控制器:

      SelectExpandQueryOption expandOpts = new SelectExpandQueryOption(null, "SalesPrices", opts.Context);
      
              Request.SetSelectExpandClause(expandOpts.SelectExpandClause);
      
              var result = expandOpts.ApplyTo(db.Items.AsQueryable(), new ODataQuerySettings());
              var resultList = new List<Items>();
      
              foreach (var item in result)
              {
                  if (item is Items)
                  {
                      resultList.Add((Items)item);
                  }
                  else if (item.GetType().Name == "SelectAllAndExpand`1")
                  {
                      var entityProperty = item.GetType().GetProperty("Instance");
                      resultList.Add((Items)entityProperty.GetValue(item));
                  }
              }
      
      
              return resultList.AsQueryable();
      

      杰伦

      【讨论】:

      • 我注意到我的扩展属性为空...我必须在 foreach 中添加一些代码.. 见下文
      【解决方案3】:

      GetItems([FromODataUri] ODataQueryOptions queryOptions)

      【讨论】:

      • 这会导致调用时出错,请查看底层错误的编辑
      猜你喜欢
      • 1970-01-01
      • 2015-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-22
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多