Criar um Singleton no OData v4 usando a API Web 2.2

por Zoe Luo

Tradicionalmente, uma entidade só poderia ser acessada se fosse encapsulada dentro de um conjunto de entidades. Mas o OData v4 fornece duas opções adicionais, Singleton e Containment, ambas compatíveis com o WebAPI 2.2.

Este artigo mostra como definir um singleton em um ponto de extremidade OData na API Web 2.2. Para obter informações sobre o que é um singleton e como você pode se beneficiar de usá-lo, consulte Usando um singleton para definir sua entidade especial. Para criar um ponto de extremidade OData V4 na API Web, consulte Criar um ponto de extremidade OData v4 usando ASP.NET Web API 2.2.

Criaremos um singleton em seu projeto de API Web usando o seguinte modelo de dados:

Modelo de dados

Um singleton chamado Umbrella será definido com base no tipo Companye um conjunto de entidades chamado Employees será definido com base no tipo Employee.

Definir o modelo de dados

  1. Defina os tipos 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. Gere o modelo EDM com base nos tipos 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(); 
    }
    

    Aqui, builder.Singleton<Company>("Umbrella") informa ao construtor de modelos para criar um singleton chamado Umbrella no modelo EDM.

    Os metadados gerados serão semelhantes aos seguintes:

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

    Nos metadados, podemos ver que a propriedade Company de navegação no Employees conjunto de entidades está associada ao singleton Umbrella. A associação é feita automaticamente por ODataConventionModelBuilder, já que só Umbrella tem o Company tipo . Se houver alguma ambiguidade no modelo, você poderá usar HasSingletonBinding para associar explicitamente uma propriedade de navegação a um singleton; HasSingletonBinding terá o mesmo efeito que usar o Singleton atributo na definição de tipo CLR:

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

Definir o controlador singleton

Assim como o controlador EntitySet, o controlador singleton herda de ODataControllere o nome do controlador singleton deve ser [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>()
        };
    } 
}

Para lidar com diferentes tipos de solicitações, as ações precisam ser predefinidas no controlador. O roteamento de atributo é habilitado por padrão no WebApi 2.2. Por exemplo, para definir uma ação para manipular a consulta Revenue usando o roteamento de Company atributo, use o seguinte:

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

Se você não estiver disposto a definir atributos para cada ação, basta definir suas ações seguindo as Convenções de Roteamento OData. Como uma chave não é necessária para consultar um singleton, as ações definidas no controlador singleton são ligeiramente diferentes das ações definidas no controlador de conjunto de entidades.

Para referência, as assinaturas de método para cada definição de ação no controlador singleton são listadas abaixo.

// 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()

Basicamente, isso é tudo o que você precisa fazer no lado do serviço. O projeto de exemplo contém todo o código para a solução e o cliente OData que mostra como usar o singleton. O cliente é criado seguindo as etapas em Criar um Aplicativo Cliente OData v4.

.

Obrigado a Leo Hu pelo conteúdo original deste artigo.