zoukankan      html  css  js  c++  java
  • 在ASP.NET Web API中使用OData的Containment

    通常情况下,一个OData的EDM(Entity Data Model)在配置的时候定义了,才可以被查询或执行各种操作。比如如下:

    builder.EntitySet<SomeModel>("SomeModels");

    可能会这样查询:http://localhost:8888/odata/SomeModels

    如果SomeModel中有一个集合导航属性,该如何获取呢?比如:

    public class SomeModel
    {
        public int Id{get;set;}
        
        public IList<AnotherModel> AnotherModels{get;set;}
    }
    
    public class AnotherModel
    {
      

    我们是否可以直接在SomeModel中获取所有的AnotherModel, 而不是通过如下方式获取:

    builder.EntitySet<AnotherModel>("AnotherModels");
    http://localhost:8888/odata/AnotherModels

    OData为我们提供了Containment,只要为某个集合导航属性加上[Contained]特性,就可以按如下方式获取某个EDM模型下的集合导航属性,比如:

    http://localhost:8888/odata/SomeModels(1)/AnotherModels

    好先定义模型。

    public class Account
    {
        public int AccountID { get; set; }
        public string Name { get; set; }
    
        [Contained]
        public IList<PaymentInstrument> PayinPIs { get; set; }
    }
    
    public class PaymentInstrument
    {
        public int PaymentInstrumentID { get; set; }
        public string FriendlyName { get; set; }
    }

    以上,一旦在PayinPIs这个集合导航属性上加上[Contained]特性,只要在controller中再提供获取集合导航属性的方法,我们就可以按如下方式,通过Account获取PaymentInstrument集合。如下:

    http://localhost:8888/odata/Accounts(100)/PayinPIs

    在WebApiConfig类中定义如下:

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            ...
    
            config.MapODataServiceRoute(
                routeName: "ODataRoute",
                routePrefix: "odata",
                model: GetModel());
        }
    
        private static IEdmModel GetModel()
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    
            builder.EntityType<PaymentInstrument>();
            builder.EntitySet<Account>("Accounts");
    
            return builder.GetEdmModel();
        }
    }


    在API端定义如下:

    public class AccountsController : ODataController
    {
    
        private static IList<Account> _accounts = null;
    
        public AccountsController()
        {
            if(_accounts==null)
            {
                _accounts = InitAccounts();
            }
        }
    
        [EnableQuery]
        public IHttpActionResult Get()
        {
            return Ok(_accounts.AsQueryable());
        }
    
        [EnableQuery]
        public IHttpActionResult GetById([FromODataUri] int key)
        {
            var account = _accounts.Single(a => a.AccountID == key);
            return Ok(account);
        }
    
        //获取Account所有的PaymentInstrument集合
        [EnableQuery]
        public IHttpActionResult GetPayinPIs([FromODataUri]int key)
        {
            var payinPIs = _accounts.Single(a => a.AccountID == key).PayinPIs;
            return Ok(payinPIs);
        }
    
        private static IList<Account> InitAccounts()
        {
            var accounts = new List<Account>()
            {
                new Account()
                {
                   AccountID = 100,
                   Name="Name100",
                   PayoutPI = new PaymentInstrument()
                   {
                       PaymentInstrumentID = 100,
                       FriendlyName = "Payout PI: Paypal",
                   },
                    PayinPIs = new List<PaymentInstrument>()
                    {
                        new PaymentInstrument()
                        {
                            PaymentInstrumentID = 101,
                            FriendlyName = "101 first PI",
                        },
                        new PaymentInstrument()
                        {
                            PaymentInstrumentID = 102,
                            FriendlyName = "102 second PI",
                        },
                    },
                },
            };
            return accounts;
        }
    }

    以上的GetPayinPIs方法可以让我们根据Account获取其集合导航属性PayinPIs。


    好,现在PayinPIs加上了[Contained]特性,也配备了具体的Action,现在开始查询:

    http://localhost:64696/odata/Accounts(100)/PayinPIs

    能查询到所有的PaymentInstrument。

    此时,PayinPIs集合导航属性在元数据中是如何呈现的呢?查询如下:

    http://localhost:64696/odata/$metadata

    相关部分为:

    <EntityType Name="Account">
        <Key>
            <PropertyRef Name="AccountID" />
        </Key>
        <Property Name="AccountID" Type="Edm.Int32" Nullable="false" />
        <Property Name="Name" Type="Edm.String" />
        <NavigationProperty Name="PayinPIs" Type="Collection(MyODataContainmentSample.PaymentInstrument)" ContainsTarget="true" />
    </EntityType>

    如果把PayinPIs上的[Contained]特性去掉呢?去掉后再次查询如下:

    http://localhost:64696/odata/Accounts(100)/PayinPIs

    返回404 NOT FOUND

    再来看去掉[Contained]特性后相关的元数据:

    <NavigationProperty Name="PayinPIs" Type="Collection(MyODataContainmentSample.PaymentInstrument)" />


    没去掉[Contained]特性之前是:
    <NavigationProperty Name="PayinPIs" Type="Collection(MyODataContainmentSample.PaymentInstrument)" ContainsTarget="true" />

    原来,在一个集合导航属性上添加[Contained]特性,实际是让ContainsTarget="true",而默认状况下,ContainsTarget="false"。

     ^_^     

  • 相关阅读:
    Solution -「HEOI/TJOI 2016」「洛谷 P2824」排序
    Solution -「国家集训队」「洛谷 P2839」Middle
    Solution -「CTSC 2018」「洛谷 P4602」混合果汁
    Solution -「CF 793G」Oleg and Chess
    Solution -「AGC 019F」「AT 2705」Yes or No
    Solution -「AGC 013E」「AT 2371」Placing Squares
    使用Spock 单元测试
    Sentinel 熔断等指标如何统计以及如何判断熔断点
    牛客多校第五场自闭
    (单调栈)Largest Rectangle in a Histogram
  • 原文地址:https://www.cnblogs.com/darrenji/p/4951701.html
Copyright © 2011-2022 走看看