Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将存储过程中的值传递和返回到视图模型_C#_Sql Server_Stored Procedures_Asp.net Core Mvc_Viewmodel - Fatal编程技术网

C# 将存储过程中的值传递和返回到视图模型

C# 将存储过程中的值传递和返回到视图模型,c#,sql-server,stored-procedures,asp.net-core-mvc,viewmodel,C#,Sql Server,Stored Procedures,Asp.net Core Mvc,Viewmodel,事先,我知道在Stackoverflow上有很多与存储过程相关的问题和答案,我知道,因为在过去的几天里,我读了很多,但我仍然无法理解创建将值返回到视图模型的存储过程的过程 这个问题分为两部分: 为什么我的代码没有成功运行,而是返回-1 如果在您的帮助下,我解决了第一个问题,那么如何将存储过程返回的数据放入视图模型列表中 我非常感谢社区能给我的任何帮助 数据库名称是Discovery 表名为Person 存储过程名称为uspGetOrgChart 我的桌子 CREATE TABLE Disco

事先,我知道在Stackoverflow上有很多与存储过程相关的问题和答案,我知道,因为在过去的几天里,我读了很多,但我仍然无法理解创建将值返回到视图模型的存储过程的过程

这个问题分为两部分:

  • 为什么我的代码没有成功运行,而是返回-1
  • 如果在您的帮助下,我解决了第一个问题,那么如何将存储过程返回的数据放入视图模型列表中
  • 我非常感谢社区能给我的任何帮助

    • 数据库名称是
      Discovery
    • 表名为
      Person
    • 存储过程名称为
      uspGetOrgChart
    我的桌子

    CREATE TABLE Discovery.dbo.Person 
    (
         ADID nvarchar(50) NOT NULL,
         First_Name nvarchar(50) NOT NULL,
         Last_Name nvarchar(50) NOT NULL,
         Report_To_ADID nvarchar(50) NULL,
         Position_ID int NULL,
         Role_ID int NULL,
         IGEMS nvarchar(50) NULL,
         DOB date NULL,
         Start_Date date NULL,
         Cost_Code nvarchar(50) NULL,
    
         PRIMARY KEY CLUSTERED (ADID),
         CONSTRAINT FK_Person_Position1 
             FOREIGN KEY (Position_ID) REFERENCES dbo.Position (Position_ID),
         CONSTRAINT FK_Person_Role 
             FOREIGN KEY (Role_ID) REFERENCES dbo.Role (Role_ID)
    )
    ON [PRIMARY]
    GO 
    
    我的存储过程当前如下所示:

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    
    ALTER PROCEDURE [dbo].[uspGetOrgChart]
        @ContactID VARCHAR(100) = 'NOE1WWD'
    AS
    BEGIN
        SET NOCOUNT ON;
    
        --grab id of @contactid
        DECLARE @Test varchar(36)
        SELECT @Test = (SELECT ADID FROM Person c1 WHERE c1.ADID = @ContactID)
    
        ;WITH StaffTree AS 
        ( 
            SELECT  
                c.ADID, 
                c.First_Name, 
                c.Last_Name,
                c.Report_To_ADID, 
                c.Report_To_ADID as Manager_ID,
                cc.First_Name AS Manager_First_Name, 
                cc.Last_Name as Manager_Last_Name, 
                cc.First_name + ' ' + cc.Last_name AS [ReportsTo], 
                c.First_Name + ' ' + c.Last_Name as EmployeeName,  
                1 AS LevelOf 
            FROM 
                Person c 
            LEFT OUTER JOIN 
                Person cc ON c.Report_To_ADID = cc.ADID 
            WHERE 
                c.ADID = @Test 
                OR (@Test IS NULL AND c.Report_To_ADID IS NULL) 
    
            UNION ALL 
    
            SELECT  
                s.ADID, 
                s.First_Name, 
                s.Last_Name, 
                s.Report_To_ADID, 
                t.ADID, 
                t.First_Name, 
                t.Last_Name, 
                t.First_Name + ' ' + t.Last_Name, 
                s.First_Name + ' ' + s.Last_Name,
                t.LevelOf + 1 
            FROM 
                StaffTree t 
            INNER JOIN 
                Person s ON t.ADID = s.Report_To_ADID 
            WHERE 
                s.Report_To_ADID = @Test 
                OR @Test IS NULL 
                OR t.LevelOf > 1 
        )
        SELECT * FROM StaffTree 
    END
    
    我已经进行了测试,上述过程按照我的预期工作,并返回以下列:

     ADID    
     First_Name
     Last_Name
     Report_To_ADID
     Manager_ID
     Manager_First_Name
     Manager_Last_Name
     ReportsTo
     EmployeeName
     LevelOf
    
    我的视图模型称为
    vmNewOrgChart

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace Discovery.ViewModels
    {
        public class vmNewOrgChart
        {
            public string ADID { get; set; }
            public string First_Name { get; set; }
            public string Last_Name { get; set; }
            public string Report_To_Adid { get; set; }
            public string Manager_ID { get; set; }
            public string Manager_First_Name { get; set; }
            public string Manager_Last_Name { get; set; }
            public string ReportsTo { get; set; }
            public string EmployeeName { get; set; }
            public int LevelOf { get; set; }
        }
    }
    
    这就是我开始完全陷入困境的地方

    public IActionResult Orgchart(string id)
    {
        var personIdParam = new SqlParameter("@ContactID", SqlDbType.VarChar);
        personIdParam.Value = id;
    
        var result = _context.Database.ExecuteSqlCommand("exec uspGetOrgChart", personIdParam);
    }
    
    上面的代码运行,但是result的值是-1,这意味着它没有返回任何内容或返回一些错误

    非常感谢您的帮助

    Derek

    方法通常用于执行操作DML查询(
    INSERT
    UPDATE
    DELETE
    ),该方法返回这些操作中受影响的行数。如果要将
    SELECT
    查询结果返回到指定的模型类中,则应将目标模型类设置为如下类型参数:

    _context.Database.SqlQuery<vmNewOrgChart>("exec uspGetOrgChart", personIdParam);
    
    相关问题:


    过程无法返回表。将函数与表返回值一起使用:

    CREATE FUNCTION  fnGetOrgChart()
    RETURNS  @rtnTable TABLE 
    (
    ---you fields
    )
    AS
    BEGIN
    DECLARE @TempTable table (id uniqueidentifier, name nvarchar(255)....)
    insert into @myTable 
    select from your stuff
    --This select returns data
    insert into @rtnTable
    SELECT ID, name FROM @mytable 
    return
    END
    
    请参阅microsoft文档中关于函数和表结果的信息

    然后打电话

    var result = context.Database.SqlQuery<vmNewOrgChart>("select * from fnGetOrgChart()");
    
    var result=context.Database.SqlQuery(“从fnGetOrgChart()中选择*”;
    
    山本哲也建议

    否则,必须调用存储来填充临时表,然后从临时表中选择数据并刷新它

    注意。您可以轻松地将参数传递给这些函数。为简洁起见省略

    谢谢大家

    谢谢,这看起来离工作更近了。当我使用代码时

    using (_context)
    {
    using (var cmd = _context.Database.GetDbConnection().CreateCommand())
    {
    cmd.CommandText = "exec uspGetOrgChart";
    cmd.CommandType = System.Data.CommandType.StoredProcedure;
    
    var personIdParam = cmd.CreateParameter();
    personIdParam.ParameterName = "ContactID";
    personIdParam.Value = id;
    
    cmd.Parameters.Add(personIdParam);
    
    _context.Database.OpenConnection();
    using (var result = cmd.ExecuteReader())
    {
    if (result.HasRows)
    {
    // do something with results
    
    }
    }
    }
    
    }
    
    我得到一个错误,从这一行找不到存储过程,该过程肯定在那里并且正在工作

    (var result = cmd.ExecuteReader())
    
    我认为这是因为代码正在关闭和打开第二个连接,所以我注释掉了这行代码

    _context.Database.OpenConnection();
    
    这导致连接未打开的错误

    我当前的上下文称为

    _Context 
    
    并且在应用程序的其余部分都在使用,我真的必须创建一个全新的上下文和连接才能运行该过程吗

    谢谢
    Derek

    感谢大家的帮助,我使用此代码成功地运行了存储过程

    using (_context)
    {
                    using (var cmd = _context.Database.GetDbConnection().CreateCommand())
                    {
                        cmd.CommandText = "uspGetOrgChart";
                        cmd.CommandType = System.Data.CommandType.StoredProcedure;
    
                        var personIdParam = cmd.CreateParameter();
                        personIdParam.ParameterName = "ContactID";
                        personIdParam.Value = id;
    
                        cmd.Parameters.Add(personIdParam);
    
                        _context.Database.OpenConnection();
                        using (var result = cmd.ExecuteReader())
                        {
                            if (result.HasRows)
                            {
                                // do something with results
    
                            }
                        }
                    }
    
                }
    

    commandtext中不需要“exec”

    您可以使用此解决方案:

     using (var cmd = _db.Database.GetDbConnection().CreateCommand())
                    {
                        cmd.CommandText = "dbo.GetCategories"; //sp name
                        cmd.CommandType = System.Data.CommandType.StoredProcedure;
                        _db.Database.OpenConnection();
                        using (var result = cmd.ExecuteReader())
                        {
                            if (result.HasRows)
                            {
                                 var List= MapToList<Category>(result);
                            }
                        }
                    }
    
    public IList<T> MapToList<T>(DbDataReader dr)
            {
                var objList = new List<T>();
                var props = typeof(T).GetRuntimeProperties();
    
                var colMapping = dr.GetColumnSchema()
                    .Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
                    .ToDictionary(key => key.ColumnName.ToLower());
    
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        T obj = Activator.CreateInstance<T>();
                        foreach (var prop in props)
                        {
                            if (colMapping.Any(a => a.Key.ToLower() == prop.Name.ToLower()))
                            {
                                var val = dr.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
                                prop.SetValue(obj, val == DBNull.Value ? null : val);
                            }
                        }
                        objList.Add(obj);
                    }
                }
                return objList;
            }
    
    使用(var cmd=_db.Database.GetDbConnection().CreateCommand())
    {
    cmd.CommandText=“dbo.GetCategories”;//sp名称
    cmd.CommandType=System.Data.CommandType.StoredProcess;
    _OpenConnection();
    使用(var result=cmd.ExecuteReader())
    {
    if(result.HasRows)
    {
    变量列表=映射列表(结果);
    }
    }
    }
    公共IList映射列表(DbDataReader dr)
    {
    var objList=新列表();
    var props=typeof(T).GetRuntimeProperties();
    var colMapping=dr.GetColumnSchema()
    .Where(x=>props.Any(y=>y.Name.ToLower()==x.ColumnName.ToLower())
    .ToDictionary(key=>key.ColumnName.ToLower());
    如果(哈斯罗博士)
    {
    while(dr.Read())
    {
    T obj=Activator.CreateInstance();
    foreach(道具中的var道具)
    {
    if(colMapping.Any(a=>a.Key.ToLower()==prop.Name.ToLower())
    {
    var val=dr.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
    prop.SetValue(对象,val==DBNull.Value?null:val);
    }
    }
    objList.Add(obj);
    }
    }
    返回对象列表;
    }
    
    您正在使用哪些数据库管理系统?(该代码是特定于产品的。)如果没有受影响的行,则存储过程将返回
    -1
    (因为您正在使用
    对相关问题设置NOCOUNT)。如果要将结果投影到模型类中,请使用
    \u context.Database.SqlQuery(“exec uspGetOrgChart”,personIdParam)相反。我使用的是SQLServer,我使用的管理软件是MS SQL Studio。为什么不使用带有表结果的函数并对其进行选择?类似这样的内容:_context.Database.SqlQuery(“选择名称,从用户()登录”).ToList();关于这些功能的更多信息:感谢您的回复和帮助,到目前为止,我似乎在断章取义,因为我没有可用的SqlQuery方法,我是否缺少一个引用?如果您使用的是EntityFramework,并且您的上下文扩展了DbContext类,那么您应该将其视为数据库属性的方法。也许是你的智慧消失了。尝试打开和关闭,而不是尝试调用实体框架核心中的存储过程。在使用部分,我调用存储过程。此sp返回类别模型列表,MapToList方法将结果映射到类别类
    
     using (var cmd = _db.Database.GetDbConnection().CreateCommand())
                    {
                        cmd.CommandText = "dbo.GetCategories"; //sp name
                        cmd.CommandType = System.Data.CommandType.StoredProcedure;
                        _db.Database.OpenConnection();
                        using (var result = cmd.ExecuteReader())
                        {
                            if (result.HasRows)
                            {
                                 var List= MapToList<Category>(result);
                            }
                        }
                    }
    
    public IList<T> MapToList<T>(DbDataReader dr)
            {
                var objList = new List<T>();
                var props = typeof(T).GetRuntimeProperties();
    
                var colMapping = dr.GetColumnSchema()
                    .Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
                    .ToDictionary(key => key.ColumnName.ToLower());
    
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        T obj = Activator.CreateInstance<T>();
                        foreach (var prop in props)
                        {
                            if (colMapping.Any(a => a.Key.ToLower() == prop.Name.ToLower()))
                            {
                                var val = dr.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
                                prop.SetValue(obj, val == DBNull.Value ? null : val);
                            }
                        }
                        objList.Add(obj);
                    }
                }
                return objList;
            }