Bill Roberts
Bill Roberts

Reputation: 1171

Using Odata enabled ASP.NET Web-API to call a Stored Procedure

All, Looking for guidance on exposing a Stored Procedure using OData.

I'm modifying an existing WEB-API app that already exposes OData. It currently exposes tables and views from SQL SERVER, and now I'm required to have it also expose Stored procedures. The current Stored Procedure will accept a bunch of parameters, and push changes to a handful of tables on the back-end database.

Here are the packages used by the project:

<packages>
  <package id="EntityFramework" version="6.1.3" targetFramework="net45" />
  <package id="EntityFramework" version="6.0.2" targetFramework="net45" />
  <package id="LinqKit" version="1.1.1" targetFramework="net45" />
  <package id="Microsoft.AspNet.Cors" version="5.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.OData" version="5.2.1" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi" version="5.2.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Cors" version="5.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.0" targetFramework="net45" />
  <package id="Microsoft.Data.Edm" version="5.6.3" targetFramework="net45" />
  <package id="Microsoft.Data.OData" version="5.6.3" targetFramework="net45" />
  <package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net45" />
  <package id="Microsoft.OData.Client" version="6.8.1" targetFramework="net45" />
  <package id="Microsoft.OData.Core" version="6.6.0" targetFramework="net45" />
  <package id="Microsoft.OData.Core" version="6.8.1" targetFramework="net45" />
  <package id="Microsoft.OData.Edm" version="6.6.0" targetFramework="net45" />
  <package id="Microsoft.OData.Edm" version="6.8.1" targetFramework="net45" />
  <package id="Microsoft.Spatial" version="6.6.0" targetFramework="net45" />
  <package id="Microsoft.Spatial" version="6.8.1" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="6.0.5" targetFramework="net45" />
  <package id="Patches.System.Web.OData" version="5.3.0-datetimefixes" targetFramework="net45" />
  <package id="System.Linq.Dynamic" version="1.0.2" targetFramework="net45" />
  <package id="System.Spatial" version="5.6.3" targetFramework="net45" />
</packages>

I've worked to follow this guide: Actions and Functions in OData v4 Using ASP.NET Web API 2.2, as I understand that naively supported Stored Procedures is not possible in OData.

I've modified my existing application, adding the model, and the wiring inside of WebApiConfig. On my first run I got the following error:

enter image description here

Goes without saying... There shouldn't be a primary key defined for a stored procedure.

Note that I'm trying to access "vw_tickets_all_tables", and still the error is thrown... inferring that the error breaks the entire application.

Here's the code I have thus far:

MODEL:

public class InsertUpdateTicketsPJMTickets : DbContext
{
    public InsertUpdateTicketsPJMTickets()
            : base("name=InsertUpdateTicketsPJMTickets")
    {
    }
    public DbSet<InsertUpdateTicketsPJMTicketsBase> InsertUpdateTicketsPJMTickets { get; set; }
}
public partial class InsertUpdateTicketsPJMTicketsBase
{
    string ticketType{set; get;}
    string category{set; get;}
    string title{set; get;}
    string details{set; get;}
    Nullable<bool> isHtml{set; get;}
    // bunches of fields left out for brevity
    string lastUpdateBy{set; get;}
    string createdBy{set; get;}
    string creationName{set; get;}
    string revisionName{set; get;}
}

WepApiConfig:

public static IEdmModel GetUOMSModel()
{
    ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    builder.ContainerName = "UOMSContext";
    builder.EntityType<Models.UOMS.DBO.InsertUpdateTicketsPJMTickets>()
        .Action("Execute");

    var function = builder.Function("GetParameters");

    function.Parameter<string>("ticketType");
    function.Parameter<string>("category");
    function.Parameter<string>("title");
    function.Parameter<string>("details");
    // bunches of fields left out for brevity
    function.Parameter<int?>("inputTicketId");
    function.Parameter<string>("lastUpdateBy");
    function.Parameter<string>("createdBy");
    function.Parameter<string>("creationName");
    function.Parameter<string>("revisionName");
    function.ReturnsCollectionFromEntitySet<Models.UOMS.DBO.InsertUpdateTicketsPJMTickets>("InsertUpdateTicketsPJMTickets");
}

I'll add a CONTROLLER once the "Key" issue is resolved.

Thank you for reading.

Upvotes: 0

Views: 1078

Answers (1)

Sam Xu
Sam Xu

Reputation: 3380

Did you add a key for the entity type InsertUpdateTicketsPJMTickets?

Because you try to add a entity type builder.EntityType<Models.UOMS.DBO.InsertUpdateTicketsPJMTickets>() and create an entity set named InsertUpdateTicketsPJMTickets.

From OData spec, each entity type is a structural type with key(s).

You can do:

  1. Call Fluent API HasKey

  2. Add attribute [key] on the property that you want to make it as key

Upvotes: 0

Related Questions