sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cómo puedo llamar a un procedimiento almacenado de SQL usando EntityFramework 7 y Asp.Net 5?

Espero haber entendido correctamente tu problema. Tiene un PROCEDIMIENTO ALMACENADO existente, por ejemplo dbo.spGetSomeData , en la base de datos, que devuelve la lista de algunos elementos con algunos campos y debe proporcionar los datos del método Web API.

La implementación podría ser sobre lo siguiente. Puede definir un vacío DbContext como:

public class MyDbContext : DbContext
{
}

y para definir appsettings.json con la cadena de conexión a la base de datos

{
  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=MyDb;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
  }
}

Debe usar Microsoft.Extensions.DependencyInjection para agregar MyDbContext a la

public class Startup
{
    // property for holding configuration
    public IConfigurationRoot Configuration { get; set; }

    public Startup(IHostingEnvironment env)
    {
        // Set up configuration sources.
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
            .AddEnvironmentVariables();
        // save the configuration in Configuration property
        Configuration = builder.Build();
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc()
            .AddJsonOptions(options => {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<MyDbContext>(options => {
                options.UseSqlServer(Configuration["ConnectionString"]);
            });
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        ...
    }
}

Ahora puede implementar su acción WebApi de la siguiente manera:

[Route("api/[controller]")]
public class MyController : Controller
{
    public MyDbContext _context { get; set; }

    public MyController([FromServices] MyDbContext context)
    {
        _context = context;
    }

    [HttpGet]
    public async IEnumerable<object> Get()
    {
        var returnObject = new List<dynamic>();

        using (var cmd = _context.Database.GetDbConnection().CreateCommand()) {
            cmd.CommandText = "exec dbo.spGetSomeData";
            cmd.CommandType = CommandType.StoredProcedure;
            // set some parameters of the stored procedure
            cmd.Parameters.Add(new SqlParameter("@someParam",
                SqlDbType.TinyInt) { Value = 1 });

            if (cmd.Connection.State != ConnectionState.Open)
                cmd.Connection.Open();

            var retObject = new List<dynamic>();
            using (var dataReader = await cmd.ExecuteReaderAsync())
            {
                while (await dataReader.ReadAsync())
                {
                    var dataRow = new ExpandoObject() as IDictionary<string, object>;
                    for (var iFiled = 0; iFiled < dataReader.FieldCount; iFiled++) {
                        // one can modify the next line to
                        //   if (dataReader.IsDBNull(iFiled))
                        //       dataRow.Add(dataReader.GetName(iFiled), dataReader[iFiled]);
                        // if one want don't fill the property for NULL
                        // returned from the database
                        dataRow.Add(
                            dataReader.GetName(iFiled),
                            dataReader.IsDBNull(iFiled) ? null : dataReader[iFiled] // use null instead of {}
                        );
                    }

                    retObject.Add((ExpandoObject)dataRow);
                }
            }
            return retObject;
        }
    }
}

El código anterior simplemente se ejecuta usando exec dbo.spGetSomeData y use dataRader para leer todos los resultados y guardarlos allí en dynamic objeto. Si hicieras $.ajax llamar desde api/My obtendrá los datos devueltos por dbo.spGetSomeData , que puede usar directamente en código JavaScript. El código anterior es muy transparente. Los nombres de los campos del conjunto de datos devuelto por dbo.spGetSomeData serán los nombres de las propiedades en el código JavaScript. No necesita administrar ninguna clase de entidad en su código C# de ninguna manera. Su código C# no tiene nombres de campos devueltos por el procedimiento almacenado. Por lo tanto, si ampliara/cambiara el código de dbo.spGetSomeData (cambie el nombre de algunos campos, agregue nuevos campos) deberá ajustar solo su código JavaScript, pero no el código C#.