如何从ASP.NET Web API执行(调用)存储过程?

时间:2018-09-06 23:12:16

标签: sql sql-server asp.net-web-api stored-procedures

今天,我一直在学习如何首先使用实体​​数据模型和代码在ASP.NET中开发Web api服务。到目前为止,我已经创建了Web服务并获得了Json格式。但是现在我不知道如何从存储过程执行中检索数据。为了说明我的问题,我开发了一个测试练习。欢迎任何帮助。

首先,我在数据库中创建了一个表,并在其中填充了一些随机信息:

 CREATE TABLE dbo.web_api_Test
 (
     Id INT,
     Name VARCHAR(255),
     Age REAL,
     Country VARCHAR(255),
     Savings REAL

     PRIMARY KEY(Id)
 );

 INSERT INTO dbo.web_api_Test(Id, Name, Age, Country, Savings)
 VALUES  (1, 'Luis', 30,'USA',45.90),
         (2, 'Keny', 19,'Netherlands',105.50),
         (3, 'Sam', 23,'Germany',5.50),
         (4, 'Deysi', 40,'Canada',22.10),
         (5, 'Eliana', 67,'Mexico',1067.50),
         (6, 'Bear', 22,'France',95.00),
         (7, 'Susan', 32,'Chile',125.70),
         (8, 'Zac', 21,'Italy',34.50),
         (9, 'Saito', 53,'Japan',10.25);

然后我创建了一个存储过程:

 CREATE PROCEDURE FindPeople 
      (@Country NVARCHAR(10)) 
 AS 
     SELECT *
     FROM dbo.web_api_Test 
     WHERE Country = @Country
 GO

使用Visual Studio 2017,我创建了用于调用Web API的所有结构。

我的实体模型类:

public partial class Modelo : DbContext
{
    public Modelo() : base("name=Modelo") 
    {
    }

    public DbSet<web_api_Test> web_api_Test { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<web_api_Test>()
            .Property(e => e.Name)
            .IsUnicode(false);

        modelBuilder.Entity<web_api_Test>()
            .Property(e => e.Country)
            .IsUnicode(false);
    }
}

我的桌子模型课

public partial class web_api_Test
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }

    [StringLength(255)]
    public string Name { get; set; }

    public float? Age { get; set; }

    [StringLength(255)]
    public string Country { get; set; }

    public float? Savings { get; set; }
 }

我的控制器类

public class web_api_TestController : ApiController
{
    private Modelo db = new Modelo();

    // GET: api/web_api_Test
    public IQueryable<web_api_Test> Getweb_api_Test()
    {
        return db.web_api_Test;
    }

    // GET: api/web_api_Test/5
    [ResponseType(typeof(web_api_Test))]
    public async Task<IHttpActionResult> Getweb_api_Test(int id)
    {
        web_api_Test web_api_Test = await db.web_api_Test.FindAsync(id);

        if (web_api_Test == null)
        {
            return NotFound();
        }

        return Ok(web_api_Test);
    }

    // PUT: api/web_api_Test/5
    [ResponseType(typeof(void))]
    public async Task<IHttpActionResult> Putweb_api_Test(int id, web_api_Test web_api_Test)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if (id != web_api_Test.Id)
        {
            return BadRequest();
        }

        db.Entry(web_api_Test).State = EntityState.Modified;

        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!web_api_TestExists(id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return StatusCode(HttpStatusCode.NoContent);
    }

    // POST: api/web_api_Test
    [ResponseType(typeof(web_api_Test))]
    public async Task<IHttpActionResult> Postweb_api_Test(web_api_Test web_api_Test)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        db.web_api_Test.Add(web_api_Test);

        try
        {
            await db.SaveChangesAsync();
        }
        catch (DbUpdateException)
        {
            if (web_api_TestExists(web_api_Test.Id))
            {
                return Conflict();
            }
            else
            {
                throw;
            }
        }

        return CreatedAtRoute("DefaultApi", new { id = web_api_Test.Id }, 
   web_api_Test);
    }

    // DELETE: api/web_api_Test/5
    [ResponseType(typeof(web_api_Test))]
    public async Task<IHttpActionResult> Deleteweb_api_Test(int id)
    {
        web_api_Test web_api_Test = await db.web_api_Test.FindAsync(id);

        if (web_api_Test == null)
        {
            return NotFound();
        }

        db.web_api_Test.Remove(web_api_Test);
        await db.SaveChangesAsync();

        return Ok(web_api_Test);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }

        base.Dispose(disposing);
    }

    private bool web_api_TestExists(int id)
    {
        return db.web_api_Test.Count(e => e.Id == id) > 0;
    }
}

这些屏幕截图是使用IIS Google时获得的结果

enter image description here

enter image description here

如何更改代码以调用存储过程FindPeople

谢谢

编辑:我已经尝试了以下代码:

    [HttpGet, Route("api/TestStoreProcN")]
    public IQueryable<web_api_Test> GetStore(String country)
    {
        var getDataLogs = db.web_api_Test.SqlQuery<web_api_Test>("exec 
   FindPeople @Country", country).AsQueryable();
        return getDataLogs;
    }

但是我遇到了以下错误:

enter image description here

基于Pranav Singh的答案,我实现了以下方法,并且可以正常工作。

答案1:

    [HttpGet, Route("api/TestProcedure/{country}")]
    public List<web_api_Test> GetList(string country)
    {

        SqlConnection connection = new SqlConnection();

        connection.ConnectionString =
        "Data Source=myserver;" +
        "Initial Catalog=mydatabase;" +
        "User id=myuser;" +
        "Password=secret;";

        connection.Open();

        string procedureName = "[dbo].[FindPeople]";
        var result = new List<web_api_Test>();
        using (SqlCommand command = new SqlCommand(procedureName, 
        connection))
        {
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.Add(new SqlParameter("@Country", country));

            using (SqlDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    int id = int.Parse(reader[0].ToString());
                    string name = reader[1].ToString();
                    float? age = float.Parse(reader[2]?.ToString());
                    string Country = reader[3].ToString();
                    float? savings = float.Parse(reader[4]?.ToString());
                    web_api_Test tmpRecord = new web_api_Test()
                    {
                        Id = id,
                        Name = name,
                        Age = age,
                        Country = country,
                        Savings = savings
                    };
                    result.Add(tmpRecord);
                }
            }
        }
        return result;
    } 

但是现在我想知道如何使用Entity Framework检索相同的结果。我该怎么办?欢迎任何参考或建议。

答案2:

最后,我找到了使用EF的解决方案:

    [HttpGet, Route("api/TestProcedure/{country}")]
    public List<web_api_Test> GetListProcedure(string country)
    {
        var parameter = new SqlParameter {
            ParameterName ="Country",
            Value =country};

        var result= db.web_api_Test.SqlQuery("EXEC FindPeople 
       @Country",parameter).ToList();

        return result;
    }

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

由于许多原因,我很长时间没有使用EF。如果您可以直接采取方法,则可以尝试以下方法:

public List<web_api_Test> GetList(string country){
    string procedureName = "[dbo].[FindPeople]";
    var result = new List<web_api_Test>();
    using (SqlCommand command = new SqlCommand(procedureName, connection))
    {
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.Add(new SqlParameter("@Country", country));

        using (SqlDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                int id = int.Parse(reader[0].ToString());
                string name  = reader[1].ToString();
                float? age = float.Parse(reader[2]?.ToString()); 
                string Country   = reader[3].ToString();
                float? savings = float.Parse(reader[4]?.ToString()); 
                web_api_Test tmpRecord = new web_api_Test()
                {
                    Id = id,
                    Name =Name ,
                    Age =age,
                    Savings =savings
                };
                result.Add(tmpRecord);
            }
        }
    }
    return result;
}

答案 1 :(得分:0)

您可以直接使用context.SqlQuery在上下文中使用基础数据库,这包括调用存储过程。例如,与此类似的东西应该起作用;

var parameter = new SqlParameter {
                     ParameterName = "Country",
                     Value = "USA"
            };

var countries= context.web_api_Test.SqlQuery<web_api_Test>("exec FindPeople @Country", parameter).ToList<web_api_Test>();

有关更多信息,请参见MSDN参考。 Raw SQL Queries