【问题标题】:C# : how to retrieve records into stored procedure using Entity Framework Core?C#:如何使用 Entity Framework Core 将记录检索到存储过程中?
【发布时间】:2019-03-01 02:25:45
【问题描述】:

我已经使用 Angular 创建了一个新的 ASP.NET Core 2.1 Web 应用程序

Visual Studio 创建一个使用 Entity Framework Core 和 ASP.NET Core MVC 的项目。

我有这个问题:我必须从存储过程中读取记录:

CREATE PROCEDURE GetEmployees
    (@PageIndex INT,
     @PageSize INT)
AS
BEGIN
    SELECT * 
    FROM employee 
    ORDER BY id 
        OFFSET @PageSize * (@PageIndex - 1) ROWS 
        FETCH NEXT @PageSize ROWS ONLY;

    SELECT COUNT(*) AS totalCount 
    FROM employee;
END

我找到了a question that almost solves my question,但不幸的是还是有一些东西不起作用。

这是我的代码:

namespace Angular.Controllers
{
    //[Produces("application/json")]
    [Route("api/Employees")]
    public class EmployeesController : Controller
    {
        private readonly ApplicationDbContext _context;

        public EmployeesController(ApplicationDbContext context)
        {
            _context = context;
        }

        // GET: api/Employees/pageIndex/1/pageSize/1
        [HttpGet("pageIndex/{pageIndex}/pageSize/{pageSize}")]
        public Task<IActionResult> GetEmployeeP([FromRoute] int pageIndex, int pageSize)
        {
            SqlParameter pageIndexParam = new SqlParameter("@PageIndex", SqlDbType.Int);
            pageIndexParam.Value = pageIndex;

            SqlParameter pageSizeParam = new SqlParameter("@pageSize", SqlDbType.Int);
            pageSizeParam.Value = pageSize;

            // SqlParameter pageIndexParam = new SqlParameter("@PageIndex", pageIndex);
            // SqlParameter pageSizeParam = new SqlParameter("@pageSize", pageSize);

            var cmd = _context.Database.GetDbConnection().CreateCommand();
            cmd.CommandText = "GetEmployees"; // The name of the stored procedure
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            // the 2 parameters to be passed to the procedure
            var param = cmd.CreateParameter();
            param.ParameterName = "@PageIndex";
            param.Value = pageIndexParam;
            cmd.Parameters.Add(param);

            var param2 = cmd.CreateParameter();
            param2.ParameterName = "@pageSize";
            param2.Value = pageSizeParam;
            cmd.Parameters.Add(param2);

            try
            {
                // connection.Open();
                // _context.Database.GetDbConnection().Open(); // it crashes after this line
                _context.Database.OpenConnection(); // it crashes after this line
                var dr = cmd.ExecuteReader(); // ArgumentException: No mapping exists from object type System.Data.SqlClient.SqlParameter to a known managed provider native type.
                List<Employee> listEmp = new List<Employee>();

                while (dr.Read())
                {
                    // Is there a faster way to read the whole record?
                    // Or should I write a line for each field?
                    Employee emp = new Employee();
                    emp.ID = System.Int32.Parse(dr["id"].ToString());
                    emp.Fname = dr["FName"].ToString();
                    emp.email = dr["email"].ToString();
                    emp.Lname = dr["LName"].ToString();
                    listEmp.Add(emp);

                    dr.NextResult();
                }

                return Ok(listEmp);
            }
            catch (Exception ex)
            {
                // how can I return an error in json format?
                throw;
            }
        }
    }
}

问题出在脚本ExecuteReader所在的那一行:

ArgumentException:不存在从对象类型 System.Data.SqlClient.SqlParameter 到已知托管提供程序本机类型的映射。

我使用 Microsoft SQL Server 在 Startup.cs 文件中,我是这样配置连接的:

services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer("Server=localhost\\SQLEXPRESS;Database=master;Trusted_Connection=True;"));

你能帮帮我吗?

也许我设法正确传递了参数(请参阅我的解决方案,在答案中)但我无法提取记录

【问题讨论】:

  • 你得到什么错误?也许连接已经打开?
  • ArgumentException:不存在从对象类型 System.Data.SqlClient.SqlParameter 到已知托管提供程序本机类型的映射。
  • 创建SqlParameter 对象时,请尝试指定数据类型并稍后设置值。例如:var pageIndexParam = new SqlParameter("@PageIndex", SqlDbType.Int); pageIndexParam.Value = pageIndex;
  • 没有。它甚至不能那样工作
  • 同样的错误?不同的错误?你需要学会停止说“它不起作用”并提供更多细节,否则没有人可以帮助你。

标签: sql-server asp.net-mvc-4 c#-4.0 entity-framework-core


【解决方案1】:

我在当前项目中使用 Entity Framework Core,并使用以下方法通过存储过程获取数据。

首先在存储过程中创建一个具有相同数量和名称的属性的模型。

假设您仅通过存储过程选择 EmployeeName ,EmployeeId。

型号。

 public class EmployeeModel
  {
    public string EmployeeName { get; set; }
    public int EmployeeId{ get; set; }
  }

转到您的 Db 上下文文件并注册您的自定义模型。

 public partial class ApplicationDbContext: DbContext
 {
 public virtual DbSet<EmployeeModel> EmployeeModel{ get; set; }
 protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<EmployeeModel>(entity =>
        { 
        });
        }
    }

你的控制器

 [HttpGet("pageIndex/{pageIndex}/pageSize/{pageSize}")]
    public Task<IActionResult> GetEmployeeP([FromRoute] int pageIndex, int pageSize)
    {
    List<EmployeeModel> employeeList = new List<EmployeeModel>();
    employeeList = _context.EmployeeModel.FromSql("GetEmployees 
    @PageIndex,@PageSize", 
    new SqlParameter("@PageIndex", pageIndex),
    new SqlParameter("@PageSize", pageSize)).ToList();
    return Ok(employeeList);
    }

【讨论】:

    【解决方案2】:

    部分解谜:

        // GET: api/Employees/pageIndex/1/pageSize/1
        [HttpGet("pageIndex/{pageIndex}/pageSize/{pageSize}")]
        public async Task<IActionResult> GetEmployeeP([FromRoute] int pageIndex, int pageSize)
        {
            _context.Database.OpenConnection();
    
            var cmd = _context.Database.GetDbConnection().CreateCommand();
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            /*
             * it's the same, it also works with these lines
                        SqlParameter pageIndexParam = new SqlParameter("PageIndex", pageIndex);
                        SqlParameter pageSizeParam = new SqlParameter("PageSize", pageSize);
                        cmd.Parameters.Add(pageIndexParam);
                        cmd.Parameters.Add(pageSizeParam);
            */
    
            cmd.CommandText = "GetEmployees"; // The name of the stored procedure
    
            // the 2 parameters to be passed to the procedure
            var param = cmd.CreateParameter();
            param.ParameterName = "@PageIndex";
            param.Value = pageIndex;
            cmd.Parameters.Add(param);
    
            var param2 = cmd.CreateParameter();
            param2.ParameterName = "@PageSize";
            param2.Value = pageSize;
            cmd.Parameters.Add(param2);
    
    
    
    
            try
            {
                System.Data.Common.DbDataReader dr = cmd.ExecuteReader();
                List<Employee> listEmp = new List<Employee>();
    
                while (dr.Read())
                {
                    // Is there a faster way to read the whole record?
                    // Or should I write a line for each field?
                    Employee emp = new Employee();
                    //emp.ID = System.Int32.Parse(dr["id"].ToString());
                    emp.ID = 1; //  it crashes after this line
                    emp.Fname = dr["FName"].ToString(); // System.IndexOutOfRangeException: FName
    
                    /*
                     * it doesn't see the columns :-(
                                        emp.email = dr["email"].ToString();
                                        emp.Lname = dr["LName"].ToString();
                    */
                    listEmp.Add(emp);
                    dr.NextResult();
                }
                return Ok(listEmp);
            }
            catch (Exception ex)
            {
                // how can I return an error in json format?
                throw;
            }
    
    
    
        }
    

    现在它稍后崩溃 当它试图读取记录时

    emp.Fname = dr["FName"].ToString();
    

    System.IndexOutOfRangeException: FName

    它没有看到列 :-(

    【讨论】:

    • 检查结果中是否存在 FName 列?
    • 是的,该列存在 :-(
    • 你只需将鼠标悬停在博士上,看看它包含什么?
    【解决方案3】:

    根据@bricelam 回答here 的内容,你可以试试这个吗?

         public Task<IActionResult> GetEmployeeP([FromRoute] int pageIndex, int pageSize)
        {
            var cmd = _context.Database.GetDbConnection().CreateCommand();
            cmd.CommandText = "GetEmployees";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
    
            cmd.Parameters.AddWithValue("@PageIndex", pageIndex);
            cmd.Parameters.AddWithValue("@PageSize", pageSize);
    
            try
            {
              //...
            }
       }
    

    如果发生任何事情,请告诉我。

    【讨论】:

    • 它无法编译:CS1061 C# 不包含 for 的定义,并且找不到接受第一个类型参数的扩展方法(您是否缺少 using 指令或程序集引用?)参见 2尝试前的行
    • AddWithValue 不存在
    • 请不要使用AddWithValue,它很糟糕并且有潜在的危险。 blogs.msmvps.com/jcoehoorn/blog/2014/05/12/…
    猜你喜欢
    • 2019-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多