Web API 2.2 を使用して OData v4 でシングルトンを作成する

作成者: Zoe Luo

従来、エンティティはエンティティ セット内にカプセル化されている場合のみアクセスできました。 ただし、OData v4 には、シングルトンと包含という 2 つの追加オプションがあり、どちらも WebAPI 2.2 でサポートされています。

この記事では、Web API 2.2 の OData エンドポイントでシングルトンを定義する方法を示します。 シングルトンとは何か、およびそれを使用することでどのような利点が得られるかについては、特別なエンティティを定義するためのシングルトンの使用に関するページを参照してください。 Web API で OData V4 エンドポイントを作成するには、「ASP.NET Web API 2.2 を使用して OData v4 エンドポイントを作成する」を参照してください。

次のデータ モデルを使用して、Web API プロジェクトにシングルトンを作成します。

Data Model

Umbrella という名前のシングルトンは型 Company に基づいて定義され、Employees という名前のエンティティ セットは型 Employee に基づいて定義されます。

データ モデルを定義する

  1. CLR 型を定義します。

    /// <summary> 
    /// Present the EntityType "Employee" 
    /// </summary> 
    public class Employee 
    {     
        public int ID { get; set; }     
        public string Name { get; set; }  
       
        [Singleton]     
        public Company Company { get; set; } 
    } 
    /// <summary> 
    /// Present company category, which is an enum type 
    /// </summary> 
    public enum CompanyCategory 
    { 
        IT = 0,     
        Communication = 1,     
        Electronics = 2,     
        Others = 3 
    } 
    /// <summary> 
    /// Present the EntityType "Company" 
    /// </summary> 
    public class Company 
    {
         public int ID { get; set; }
         public string Name { get; set; }
         public Int64 Revenue { get; set; }
         public CompanyCategory Category { get; set; }
         public List<Employee> Employees { get; set; } 
    }
    
  2. CLR 型に基づいて EDM モデルを生成します。

    public static IEdmModel GetEdmModel() 
    { 
        ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<Employee>("Employees"); builder.Singleton<Company>("Umbrella");
        builder.Namespace = typeof(Company).Namespace;
        return builder.GetEdmModel(); 
    }
    

    ここでは、builder.Singleton<Company>("Umbrella") により、EDM モデルで Umbrella という名前のシングルトンを作成するようにモデル ビルダーに指示します。

    生成されたメタデータは次のようになります。

    <EntityContainer Name="Container"> 
      <EntitySet Name="Employees" EntityType="ODataSingletonSample.Employee"> 
        <NavigationPropertyBinding Path="Company" Target="Umbrella"/> 
      </EntitySet> 
      <Singleton Name="Umbrella" Type="ODataSingletonSample.Company"> 
        <NavigationPropertyBinding Path="Employees" Target="Employees"/> 
      </Singleton> 
    </EntityContainer>
    

    メタデータから、Employees エンティティ セット内のナビゲーション プロパティ Company がシングルトン Umbrella にバインドされていることがわかります。 バインドは ODataConventionModelBuilderによって自動的に行われます。Umbrella にのみ Company 型があるためです。 モデルにあいまいさがある場合は、HasSingletonBinding を使用して、ナビゲーション プロパティをシングルトンに明示的にバインドできます。HasSingletonBinding には、CLR 型定義で Singleton 属性を使用する場合と同じ効果があります。

    EntitySetConfiguration<Employee> employeesConfiguration = 
        builder.EntitySet<Employee>("Employees"); 
    employeesConfiguration.HasSingletonBinding(c => c.Company, "Umbrella");
    

シングルトン コントローラーを定義する

EntitySet コントローラーと同様に、シングルトン コントローラーは ODataController から継承され、シングルトン コントローラー名は [singletonName]Controller である必要があります。

public class UmbrellaController : ODataController 
{
    public static Company Umbrella;
    static UmbrellaController()
    {
        InitData();
    }
    private static void InitData()
    {
        Umbrella = new Company()
        {
            ID = 1,
            Name = "Umbrella",
            Revenue = 1000,
            Category = CompanyCategory.Communication,
            Employees = new List<Employee>()
        };
    } 
}

さまざまな種類の要求を処理するには、コントローラーでアクションを事前に定義する必要があります。 属性ルーティングは、WebApi 2.2 では既定で有効になっています。 たとえば、属性ルーティングを使用して Company からの Revenue のクエリを処理するアクションを定義するには、次のコマンドを使用します。

[ODataRoute("Umbrella/Revenue")] 
public IHttpActionResult GetCompanyRevenue() 
{
     return Ok(Umbrella.Revenue); 
}

各アクションの属性を定義する必要がない場合は、OData ルーティング規則に従ってアクションを定義するだけです。 シングルトンのクエリにキーは必要ないため、シングルトン コントローラーで定義されているアクションは、エンティティセット コントローラーで定義されているアクションとは若干異なります。

参照用に、シングルトン コントローラー内のすべてのアクション定義のメソッド シグネチャの一覧を以下に示します。

// Get Singleton 
// ~/singleton 
public IHttpActionResult Get() 
public IHttpActionResult GetUmbrella() 

// Get Singleton 
// ~/singleton/cast 
public IHttpActionResult GetFromSubCompany() 
public IHttpActionResult GetUmbrellaFromSubCompany() 

// Get Singleton Property 
// ~/singleton/property  
public IHttpActionResult GetName() 
public IHttpActionResult GetNameFromCompany() 

// Get Singleton Navigation Property 
// ~/singleton/navigation  
public IHttpActionResult GetEmployees() 
public IHttpActionResult GetEmployeesFromCompany() 

// Update singleton by PUT 
// PUT ~/singleton 
public IHttpActionResult Put(Company newCompany) 
public IHttpActionResult PutUmbrella(Company newCompany) 

// Update singleton by Patch 
// PATCH ~/singleton 
public IHttpActionResult Patch(Delta<Company> item) 
public IHttpActionResult PatchUmbrella(Delta<Company> item) 

// Add navigation link to singleton 
// POST ~/singleton/navigation/$ref 
public IHttpActionResult CreateRef(string navigationProperty, [FromBody] Uri link) 

// Delete navigation link from singleton 
// DELETE ~/singleton/navigation/$ref?$id=~/relatedKey 
public IHttpActionResult DeleteRef(string relatedKey, string navigationProperty) 

// Add a new entity to singleton navigation property 
// POST ~/singleton/navigation 
public IHttpActionResult PostToEmployees([FromBody] Employee employee) 

// Call function bounded to singleton 
// GET ~/singleton/function() 
public IHttpActionResult GetEmployeesCount()

基本的に、サービス側で行う必要があるのはこれだけです。 サンプル プロジェクトには、ソリューションのすべてのコードと、シングルトンの使用方法を示す OData クライアントが含まれています。 クライアントは、OData v4 クライアント アプリの作成に関するページの手順に従って構築されます。

この記事のオリジナル コンテンツの作成者である Leo Hu に感謝します。