zoukankan      html  css  js  c++  java
  • .NET Core开发日志——OData

    简述

    OData,即Open Data Protocol,是由微软在2007年推出的一款开放协议,旨在通过简单、标准的方式创建和使用查询式及交互式RESTful API。

    类库

    在.NET Core中想要使用OData功能的话需要添加Microsoft.AspNetCore.OData包。

    dotnet add package Microsoft.AspNetCore.OData
    

    准备模型类

    public class Address
    {
        public string City { get; set; }
        public string Street { get; set; }
    }
    public enum Category
    {
        Book,
        Magazine,
        EBook
    }
    public class Press
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public Category Category { get; set; }
    }
    public class Book
    {
        public int Id { get; set; }
        public string ISBN { get; set; }
        public string Title { get; set; }
        public string Author { get; set; }
        public decimal Price { get; set; }
        public Address Address { get; set; }
        public Press Press { get; set; }
    }
    

    创建Edm模型

    OData使用EDM,即Entity Data Model来描述数据的结构。在Startup文件中添加创建方法。

    private static IEdmModel GetEdmModel()
    {
        var builder = new ODataConventionModelBuilder();
        builder.EntitySet<Book>("Books");
        builder.EntitySet<Press>("Presses");
        return builder.GetEdmModel();
    }
    

    注册OData服务

    在Startup文件的ConfigureServices方法里注册OData服务。

    services.AddOData();
    services.AddMvc(options =>
        {
            options.EnableEndpointRouting = false;
        }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    

    这里要注意的是在.NET Core 2.2里,默认已经有终结点,所以要使用OData的终结点的话需要将默认选项禁用掉。

    注册OData终结点

    同样在Startup文件里,在其Configure方法内将原来的注册路由内容改为注册OData的终结点。

    app.UseMvc(b =>
    {
        b.MapODataServiceRoute("odata", "odata", GetEdmModel());
    });
    

    显示元数据

    运行程序后访问https://localhost:5001/odata/$metadata地址,可以看到所有可用模型的元数据。

    <edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
        <edmx:DataServices>
            <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="Default">
                <EntityType Name="Book">
                    <Key>
                        <PropertyRef Name="Id"/>
                    </Key>
                    <Property Name="Id" Type="Edm.Int32" Nullable="false"/>
                    <Property Name="ISBN" Type="Edm.String"/>
                    <Property Name="Title" Type="Edm.String"/>
                    <Property Name="Author" Type="Edm.String"/>
                    <Property Name="Price" Type="Edm.Decimal" Nullable="false"/>
                    <Property Name="Address" Type="Default.Address"/>
                    <NavigationProperty Name="Press" Type="Default.Press"/>
                </EntityType>
                <EntityType Name="Press">
                    <Key>
                        <PropertyRef Name="Id"/>
                    </Key>
                    <Property Name="Id" Type="Edm.Int32" Nullable="false"/>
                    <Property Name="Name" Type="Edm.String"/>
                    <Property Name="Email" Type="Edm.String"/>
                    <Property Name="Category" Type="Default.Category" Nullable="false"/>
                </EntityType>
                <ComplexType Name="Address">
                    <Property Name="City" Type="Edm.String"/>
                    <Property Name="Street" Type="Edm.String"/>
                </ComplexType>
                <EnumType Name="Category">
                    <Member Name="Book" Value="0"/>
                    <Member Name="Magazine" Value="1"/>
                    <Member Name="EBook" Value="2"/>
                </EnumType>
                <EntityContainer Name="Container">
                    <EntitySet Name="Books" EntityType="Default.Book">
                        <NavigationPropertyBinding Path="Press" Target="Presses"/>
                    </EntitySet>
                    <EntitySet Name="Presses" EntityType="Default.Press"/>
                </EntityContainer>
            </Schema>
        </edmx:DataServices>
    </edmx:Edmx>
    

    创建Controller

    本文实例中不考虑数据库的操作,故而使用hard code方式构建必要的模型对象。

    public class BooksController : ODataController
    {
        private static IList<Book> Books {get; set;}
        public BooksController()
        {
            Books = new List<Book>
            {
                new Book
                {
                    Id = 1,
                    ISBN = "111-0-321-56789-1",
                    Title = "Calculus",
                    Price = 66.6m,
                    Address = new Address
                    {
                        City = "Shanghai",
                        Street = "Beijin Xi Road"
                    },
                    Press = new Press
                    {
                        Id = 1,
                        Name = "Shanghai Tongji",
                        Category = Category.Book
                    }
                },
                new Book
                {
                    Id = 2,
                    ISBN = "222-2-654-00000-2",
                    Title = "Linear Algebra",
                    Price = 53.2m,
                    Address = new Address
                    {
                        City = "Shanghai",
                        Street = "Beijin Dong Road"
                    },
                    Press = new Press
                    {
                        Id = 2,
                        Name = "Shanghai Fudan",
                        Category = Category.EBook
                    }
                }            
            };   
        }
    
        [EnableQuery]
        public IActionResult Get()
        {
            return Ok(Books);
        }
    
        [EnableQuery]
        public IActionResult Get(int key)
        {
            return Ok(Books.FirstOrDefault(b => b.Id == key));
        }
    }
    

    EnableQuery特性在需要高级查询的场景时必须添加。

    查询

    加入Controller之后,访问https://localhost:5001/odata/Books地址,可得到所有Book数据。

    {
        "@odata.context": "https://localhost:5001/odata/$metadata#Books",
        "value": [
            {
                "Id": 1,
                "ISBN": "111-0-321-56789-1",
                "Title": "Calculus",
                "Author": null,
                "Price": 66.6,
                "Address": {
                    "City": "Shanghai",
                    "Street": "Beijin Xi Road"
                }
            },
            {
                "Id": 2,
                "ISBN": "222-2-654-00000-2",
                "Title": "Linear Algebra",
                "Author": null,
                "Price": 53.2,
                "Address": {
                    "City": "Shanghai",
                    "Street": "Beijin Dong Road"
                }
            }
        ]
    }
    

    访问https://localhost:5001/odata/Books(1)地址,可得到key值为1的Book数据。

    {
        "@odata.context": "https://localhost:5001/odata/$metadata#Books/$entity",
        "Id": 1,
        "ISBN": "111-0-321-56789-1",
        "Title": "Calculus",
        "Author": null,
        "Price": 66.6,
        "Address": {
            "City": "Shanghai",
            "Street": "Beijin Xi Road"
        }
    }
    

    高级查询

    如果想要使用OData查询的高级功能,可以在注册终结点时额外加上相应的配置。

    app.UseMvc(b =>
    {
        b.Select().Expand().Filter().OrderBy().MaxTop(100).Count();
        b.MapODataServiceRoute("odata", "odata", GetEdmModel());
    });
    

    访问网址时加上所需的查询内容:
    https://localhost:5001/odata/Books?$select=Id,Title

    {
        "@odata.context": "https://localhost:5001/odata/$metadata#Books(Id,Title)",
        "value": [
            {
                "Id": 1,
                "Title": "Calculus"
            },
            {
                "Id": 2,
                "Title": "Linear Algebra"
            }
        ]
    }
    

    如果想要按特定条件过滤数据内容的话也很容易:
    https://localhost:5001/odata/Books?$filter=Price%20le%2060

    {
        "@odata.context": "https://localhost:5001/odata/$metadata#Books",
        "value": [
            {
                "Id": 2,
                "ISBN": "222-2-654-00000-2",
                "Title": "Linear Algebra",
                "Author": null,
                "Price": 53.2,
                "Address": {
                    "City": "Shanghai",
                    "Street": "Beijin Dong Road"
                }
            }
        ]
    }
    

    总结

    不难看出,OData的真正魅力在于其对那些高级查询功能的支持,所以在创建RESTful API时,不妨考虑使用OData,这样应该能减少许多不必要的代码工作。

  • 相关阅读:
    DragDrop 注册失败的问题
    《精通.NET互操作:P/Invoke,C++ Interop和COM Interop》推荐的工具列表
    勇于探索,及时总结,拥有自信!个人工作感受总结篇……
    C#4.0新特性对.NET互操作的影响(转载)
    UCHome: IP控制
    UCHome: SQL注入式攻击
    Windows下Cygwin模拟GCC开发
    序列化和反序列化
    UCHome: 解读common.php(转)
    UCHome: 提交检查
  • 原文地址:https://www.cnblogs.com/kenwoo/p/10360260.html
Copyright © 2011-2022 走看看