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