【问题标题】:Implementing OData with WebApi and Mapped Models使用 WebApi 和映射模型实现 OData
【发布时间】:2013-05-11 16:21:34
【问题描述】:

我正在尝试在 WebApi 中实现 OData。我正在使用存储库模式和 EF5(在后端),这仍然与我找到的所有示例一致。这就是事情出问题的地方。我试图将 EF 生成的类隐藏在控制器中使用 AutoMapper 映射的模型后面。我看到的示例似乎返回了回购中的任何内容

我不想将 OData 参数(应用于已映射的结果)应用到控制器中,而是应用在存储库中,以保留延迟执行的值。我可以将 ODataCriteria 传递到存储库,但是当我尝试 Appy 时,我收到一个错误,因为似乎选项/结果是从表示层而不是 IQueryable 输入到 IQueryable 的。

我在另一个帖子中看到其他人对此有所回避,但是,这只是帖子的一小部分,似乎没有帮助。

还有其他人处理过这个吗?我真的不想公开 EF 类。哦,我先用DB。

提前谢谢...

【问题讨论】:

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


    【解决方案1】:

    这里有一些代码可以说明您的要求。

    要获得结果,您需要确保查询已被执行(使用ToList())。最有效的方法是添加分页(奖励)并返回一个PageResult<> 对象。

    public PageResult<WebPoco> Get(ODataQueryOptions<WebPoco> queryOptions)
    {
        var data2 = DatabaseData();
    
        //Create a set of ODataQueryOptions for the internal class
        ODataModelBuilder modelBuilder = new ODataConventionModelBuilder();
        modelBuilder.EntitySet<DatabasePoco>("DatabasePoco"); 
        var context = new ODataQueryContext(
             modelBuilder.GetEdmModel(), typeof(DatabasePoco));
        var newOptions = new ODataQueryOptions<DatabasePoco>(context, Request);
    
        var t = new ODataValidationSettings() { MaxTop = 25 };
        var s = new ODataQuerySettings() { PageSize = 25 };
        newOptions.Validate(t);
        IEnumerable<DatabasePoco> results =
            (IEnumerable<DatabasePoco>)newOptions.ApplyTo(data2, s);
    
        int skip = newOptions.Skip == null ? 0 : newOptions.Skip.Value;
        int take = newOptions.Top == null ? 25 : newOptions.Top.Value;
    
        List<DatabasePoco> internalResults = results.Skip(skip).Take(take).ToList();
    
        // map from DatabasePoco to WebPoco here:
        List<WebPoco> webResults; 
    
        PageResult<WebPoco> page =
            new PageResult<WebPoco>(
                webResults, Request.GetNextPageLink(), Request.GetInlineCount());
    
        return page;
    }
    

    这是 using 语句

    using System.Web.Http;
    using System.Web.Http.OData;
    using System.Web.Http.OData.Builder;
    using System.Web.Http.OData.Query;
    

    测试类

    public class WebPoco
    {
        public int id { get; set; }
        public string name { get; set; }
        public string type { get; set; }
    }
    
    public class DatabasePoco
    {
        public int id { get; set; }
        public string name { get; set; }
        public string type { get; set; }
    }
    

    还有一些测试数据

    private IQueryable<DatabasePoco> DatabaseData()
    {
        return (
            new DatabasePoco[] { 
                new DatabasePoco() { id = 1, name = "one", type = "a" },
                new DatabasePoco() { id = 2, name = "two", type = "b" },
                new DatabasePoco() { id = 3, name = "three", type = "c" },
                new DatabasePoco() { id = 4, name = "four", type = "d" },
                new DatabasePoco() { id = 5, name = "five", type = "e" },
                new DatabasePoco() { id = 6, name = "six", type = "f" },
                new DatabasePoco() { id = 7, name = "seven", type = "g" },
                new DatabasePoco() { id = 8, name = "eight", type = "h" },
                new DatabasePoco() { id = 9, name = "nine", type = "i" }
            })
            .AsQueryable();
    }
    

    【讨论】:

    • 我喜欢这种方法,不幸的是,我正在使用旧数据库并收到以下错误...复杂类型 x 通过属性 Z 引用实体类型 Y。我似乎找不到谷歌上关于这个的任何事情,我只能假设它表明循环参考或其他东西的潜力......
    • @Lenny - ToList() 应该从等式中删除分贝。但是对于 EF 映射,谁知道呢?!它可能与代理、延迟加载等有关。哪条线失败了?
    • 检查这是否有用...stackoverflow.com/questions/15438195/… 谢谢
    • 经过一番努力,您的第一个建议解决了我的问题,非常感谢...
    【解决方案2】:

    如果您返回的 Queryable 是通过 dbContext.dbSet.Select(x => new Model { Id = x.Id}) 机制而不是 AutoMapper。然后在 Queryable 上应用条件可以由 EF LINQ 提供程序自动转换和评估。否则,您将不得不编写一个自定义 LINQ 提供程序,它将表达式从基于 Model 属性的表达式更改为脱离 EF_Class 属性的表达式。

    【讨论】:

    • 嗯,不喜欢那个。如果我使用 EF 类,那么我将无法隐藏 id 属性(以及其他 id)以支持作为资源 uri 的导航属性。可能仍然可能的唯一方法是通过一些丑陋的部分类工作或更改生成 EF 类的 t4 模板。我要解决这个问题了吗?我真的应该只分享 EF 课程吗?
    猜你喜欢
    • 2012-07-03
    • 2018-06-29
    • 2014-06-17
    • 2018-11-21
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-14
    相关资源
    最近更新 更多