Создание единственного элемента в OData v4 с помощью веб-API 2,2

по Зое Луо

Обычно доступ к сущности можно получить только в том случае, если она была инкапсулирована в набор сущностей. Но OData v4 предоставляет два дополнительных параметра: Singleton и Contain, которые поддерживаются WebAPI 2,2.

В этой статье показано, как определить одноэлементный экземпляр в конечной точке OData в веб-API 2,2. Сведения о том, что такое одноэлементное и в чем преимущества его использования, см. в разделе Использование одноэлементного набора для определения особой сущности. Чтобы создать конечную точку OData v4 в веб-API, см. раздел Создание конечной точки OData v4 с помощью веб-API ASP.NET 2,2.

Мы создадим одноэлементный экземпляр в проекте веб-API, используя следующую модель данных:

Модель данных

Одноэлементное имя с именем Umbrella будет определено на основе типа Company, а набор сущностей с именем Employees будет определяться на основе типа Employee.

Решение, используемое в этом руководстве, можно скачать на сайте CodePlex.

Определение модели данных

  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. Создание модели EDM на основе типов CLR.

    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") указывает построителю моделей создать одноэлементное множество с именем Umbrella в модели EDM.

    Созданные метаданные будут выглядеть следующим образом:

    <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>
    

    Из метаданных можно увидеть, что свойство навигации, Company в наборе сущностей Employees, привязано к UmbrellaSingleton. Привязка выполняется автоматически ODataConventionModelBuilder, так как только Umbrella имеет тип Company. Если в модели имеется какая-либо неоднозначность, можно использовать HasSingletonBinding, чтобы явно привязать свойство навигации к одноэлементному экземпляру. HasSingletonBinding действует так же, как и атрибут Singleton в определении типа CLR:

    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. Например, чтобы определить действие по обработке запросов Revenue от Company с помощью маршрутизации атрибутов, используйте следующую команду:

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

Если вы не хотите определять атрибуты для каждого действия, просто определите действия, следующие за соглашениями о маршрутизации OData. Поскольку ключ не требуется для запроса одноэлементного экземпляра, действия, определенные в контроллере Singleton, немного отличаются от действий, определенных в контроллере EntitySet.

Для справки сигнатуры методов для каждого определения действия в одноэлементном контроллере перечислены ниже.

// 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, который показывает, как использовать Singleton. Клиент создается, выполнив действия, описанные в разделе Создание клиентского приложения OData для версии 4.

.

Благодарим вас за первоначальное содержимое этой статьи, Leo Hu.