Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como posso chamar um procedimento armazenado SQL usando EntityFramework 7 e Asp.Net 5


Espero ter entendido corretamente o seu problema. Você possui STORED PROCEDURE, por exemplo dbo.spGetSomeData , no banco de dados, que retorna a lista de alguns itens com alguns campos e você precisa fornecer os dados do método Web API.

A implementação pode ser sobre o seguinte. Você pode definir um vazio DbContext Como:
public class MyDbContext : DbContext
{
}

e para definir appsettings.json com a string de conexão ao banco de dados
{
  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=MyDb;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
  }
}

Você deve usar Microsoft.Extensions.DependencyInjection para adicionar MyDbContext ao
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)
    {
        ...
    }
}

Agora você pode implementar sua ação WebApi da seguinte forma:
[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;
        }
    }
}

O código acima é executado usando exec dbo.spGetSomeData e use o dataRader para ler todos os resultados e salvá-los em dynamic objeto. Se você fizer $.ajax chamada de api/My você obterá os dados retornados de dbo.spGetSomeData , que você pode usar diretamente no código JavaScript. O código acima é muito transparente. Os nomes dos campos do conjunto de dados retornados por dbo.spGetSomeData serão os nomes das propriedades no código JavaScript. Você não precisa gerenciar nenhuma classe de entidade em seu código C# de forma alguma. Seu código C# não tem nomes de campos retornados do procedimento armazenado. Assim, se você estender/alterar o código de dbo.spGetSomeData (renomeie alguns campos, adicione novos campos) você precisará ajustar apenas seu código JavaScript, mas nenhum código C#.