Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.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
Stored procedures asp.net mvc:.net核心:如何将存储的过程结果集映射到类字段_Stored Procedures_Asp.net Core - Fatal编程技术网

Stored procedures asp.net mvc:.net核心:如何将存储的过程结果集映射到类字段

Stored procedures asp.net mvc:.net核心:如何将存储的过程结果集映射到类字段,stored-procedures,asp.net-core,Stored Procedures,Asp.net Core,我得到了一个简单的模型类: 公共类PrvProduct { 我正在尝试使用.net core调用一个存储的proc,它工作正常,返回一个PrvProduct对象列表。问题是:除非我自己用代码填充它们,否则它们的字段是空的。ProductId总是在那里,不知道为什么(可能是因为我在那里键入了[key]属性?) 是否有一种简单的方法可以将类字段映射到结果集,如在ado.net中(我只需要执行SQLDataAdapter.Fill(MyDataTable),MyDataTable字段将按字段名具有值)

我得到了一个简单的模型类:

公共类PrvProduct {

我正在尝试使用.net core调用一个存储的proc,它工作正常,返回一个PrvProduct对象列表。问题是:除非我自己用代码填充它们,否则它们的字段是空的。ProductId总是在那里,不知道为什么(可能是因为我在那里键入了[key]属性?)

是否有一种简单的方法可以将类字段映射到结果集,如在ado.net中(我只需要执行SQLDataAdapter.Fill(MyDataTable),MyDataTable字段将按字段名具有值)…还是每次都必须执行下面的选项2

非常感谢

字符串sqlQuery=“EXEC Maint.GetProductList”“+sNameFilter+”; //选项1:这在每个PRVPProduct的字段中不获取值(ProductId获取值可能是因为其[key],其他的则不获取) IQueryable results=_context.Products.FromSql(sqlQuery.AsNoTracking()

//选项2:这是可行的,但是……我是否必须对调用的每个存储过程、每个字段都这样做,或者是否有更好的方法将类字段映射到返回的结果字段?
List oList=新列表();
使用(var命令=_context.Database.GetDbConnection().CreateCommand())
{
command.CommandText=sqlQuery;
command.CommandType=CommandType.Text;
_context.Database.OpenConnection();
使用(var result=command.ExecuteReader())
{
while(result.Read())
{
//映射到您的实体
oList.Add(新PRV产品)
{
ProductId=result.GetInt32(0),
ProductName=result.GetString(1)
});
}
}
}

在EF Core中,如果您使用一个数据库集实体执行存储过程,它将自动映射。问题是,在许多情况下,您需要将存储过程映射到DTO,例如,DTO不是数据库集实体的一部分。在这些情况下,您需要返回时间并手动映射,这是浪费时间的e

为了避免手动映射数据读取器,我添加了一系列扩展方法来为您进行映射。代码并不完美,我仍在改进,但在大多数情况下已经足够好了

一旦添加了我将在下面描述的扩展方法,您就可以这样使用它:

return dbContext.Database.SqlQuery<SalesReportDTO>("spGetSalesReport",
                SqlParameterBuilder.Build("customerId", customerId),
                SqlParameterBuilder.Build("dateFrom", from),
                SqlParameterBuilder.Build("dateTo", to)).ToList();

\u context.Products.FromSql(sqlQuery)
应该完全按照您想要的方式工作。如果不是这样,那么就有一些问题是您在这里单独提供的内容看不出来的。我的最佳猜测是您遇到了映射问题。要使
FromSql
在您的上下文中映射到实体类型,列类型必须与您的类中的类型匹配。我开始t it!属性必须有get\set才能工作。我更改了类定义,它工作了:公共类prvpproduct{[Key]public Int32 ProductId{get;set;}public Int32 ProductLineId{get;set;}public String MfgPartNumber{get;set;}公共字符串产品名称{get;set;}公共字符串产品描述{get;set;}
        //option 2: this works, but... do i have to do this for every stored proc i call, every field, or is there a beter way to map class fields to returned results fields?
        List<PrvProduct> oList = new List<PrvProduct>();
        using (var command = _context.Database.GetDbConnection().CreateCommand())
        {
            command.CommandText = sqlQuery;
            command.CommandType = CommandType.Text;

            _context.Database.OpenConnection();

            using (var result = command.ExecuteReader())
            {
                while (result.Read())
                {
                    // Map to your entity
                    oList.Add(new PrvProduct
                    {
                        ProductId = result.GetInt32(0),
                        ProductName = result.GetString(1)
                    });
                }
            }
        }
return dbContext.Database.SqlQuery<SalesReportDTO>("spGetSalesReport",
                SqlParameterBuilder.Build("customerId", customerId),
                SqlParameterBuilder.Build("dateFrom", from),
                SqlParameterBuilder.Build("dateTo", to)).ToList();
    public static class DatabaseFacadeExtensions
    {
        public static List<T> SqlQuery<T>(this DatabaseFacade database, string query, params SqlParameter[] parameters)
        {
            return SqlQuery<T>(database, query, null, CommandType.StoredProcedure, parameters);
        }

        public static List<T> SqlQuery<T>(this DatabaseFacade database, string query, CommandType commandType, params SqlParameter[] parameters)
        {
            return SqlQuery<T>(database, query, null, commandType, parameters);
        }

        public static List<T> SqlQuery<T>(this DatabaseFacade database, string query, int? commandTimeout, params SqlParameter[] parameters)
        {
            return SqlQuery<T>(database, query, commandTimeout, CommandType.StoredProcedure, parameters);
        }

        public static List<T> SqlQuery<T>(this DatabaseFacade database, string query, int? commandTimeout, CommandType commandType, params SqlParameter[] parameters)
        {
            using (var cmd = database.GetDbConnection().CreateCommand())
            {
                cmd.CommandText = query;
                cmd.CommandType = commandType;
                if (commandTimeout.HasValue)
                {
                    cmd.CommandTimeout = commandTimeout.Value;
                }
                cmd.Parameters.AddRange(parameters);

                if (cmd.Connection.State == System.Data.ConnectionState.Closed)
                {
                    cmd.Connection.Open();
                }

                try
                {
                    using (var reader = cmd.ExecuteReader())
                    {
                        return reader.MapToList<T>();
                    }
                }
                finally
                {
                    cmd.Connection.Close();
                }
            }
        }

    }
public static class DbDataReaderExtensions
{
    public static List<T> MapToList<T>(this DbDataReader dr)
    {
        var objList = new List<T>();

        if (dr.HasRows)
        {
            bool isSingleValue = typeof(T).IsPrimitive || typeof(T) == typeof(string);
            IEnumerable<PropertyInfo> props = null;
            Dictionary<string, DbColumn> colMapping = null;

            if (!isSingleValue)
            {
                props = typeof(T).GetRuntimeProperties();
                colMapping = dr.GetColumnSchema()
                    .Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
                    .ToDictionary(key => key.ColumnName.ToLower());
            }

            while (dr.Read())
            {
                T obj;
                if (isSingleValue)
                {
                    obj = (T)dr.GetValue(0);

                }
                else
                {
                    obj = Activator.CreateInstance<T>();
                    foreach (var prop in props)
                    {
                        string propertyName = prop.Name.ToLower();
                        if (!colMapping.ContainsKey(propertyName))
                        {
                            continue;
                        }

                        var val = dr.GetValue(colMapping[propertyName].ColumnOrdinal.Value);
                        if (val != DBNull.Value)
                        {
                            // enum property
                            if (prop.PropertyType.IsEnum)
                            {
                                prop.SetValue(obj, Enum.ToObject(prop.PropertyType, val));
                            }
                            // nullable enum property
                            if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) && Nullable.GetUnderlyingType(prop.PropertyType).IsEnum)
                            {
                                prop.SetValue(obj, Enum.ToObject(Nullable.GetUnderlyingType(prop.PropertyType), val));
                            }
                            else
                            {
                                prop.SetValue(obj, val);
                            }
                        }
                    }
                }

                objList.Add(obj);
            }
        }

        return objList;
    }

    public static T MapToObject<T>(this DbDataReader dr)
    {
        var props = typeof(T).GetRuntimeProperties();

        if (dr.HasRows)
        {
            var colMapping = dr.GetColumnSchema()
                .Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
                .ToDictionary(key => key.ColumnName.ToLower());

            if (dr.Read())
            {
                T obj = Activator.CreateInstance<T>();
                foreach (var prop in props)
                {
                    var val = dr.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
                    prop.SetValue(obj, val == DBNull.Value ? null : val);
                }

                return obj;
            }
        }

        return default(T);
    }

}
    public class SqlParameterBuilder
    {
        public static SqlParameter Build(string name, bool? value)
        {
            if (value.HasValue)
            {
                return new SqlParameter() { ParameterName = name, Value = value.Value };
            }

            return new SqlParameter() { ParameterName = name, Value = DBNull.Value };
        }

        public static SqlParameter Build(string name, int? value)
        {
            if (value.HasValue)
            {
                return new SqlParameter() { ParameterName = name, Value = value.Value };
            }

            return new SqlParameter() { ParameterName = name, Value = DBNull.Value };
        }


        public static SqlParameter Build(string name, string value)
        {
            if (value != null)
            {
                return new SqlParameter() { ParameterName = name, Value = value };
            }

            return new SqlParameter() { ParameterName = name, Value = DBNull.Value };
        }

        public static SqlParameter Build(string name, DateTime? value)
        {
            if (value != null)
            {
                return new SqlParameter { ParameterName = name, SqlDbType = SqlDbType.DateTime, Value = value };
            }

            return new SqlParameter() { ParameterName = name, Value = DBNull.Value };
        }

        public static SqlParameter Build(string name, Guid? value)
        {
            if (value.HasValue)
            {
                return new SqlParameter { ParameterName = name, SqlDbType = SqlDbType.UniqueIdentifier, Value = value };
            }

            return new SqlParameter() { ParameterName = name, Value = DBNull.Value };
        }

        public static SqlParameter Build(string name, int[] values)
        {
            SqlParameter par = new SqlParameter(name, SqlDbType.Structured);
            par.TypeName = "dbo.IntParameterList";
            DataTable dt = new DataTable();
            dt.Columns.Add("id", typeof(int));
            par.Value = dt;

            if (values != null)
            {
                foreach (int value in values.Where(p => p != 0))
                {
                    dt.Rows.Add(value);
                }
            }

            return par;
        }

        public static SqlParameter Build(string name, string[] values, VarcharParameterListEnum varcharParameterListType = VarcharParameterListEnum.Varchar50)
        {
            SqlParameter par = new SqlParameter(name, SqlDbType.Structured);
            switch(varcharParameterListType)
            {
                case VarcharParameterListEnum.Varchar15:
                    par.TypeName = "dbo.Varchar15ParameterList";
                    break;
                case VarcharParameterListEnum.Varchar50:
                    par.TypeName = "dbo.Varchar50ParameterList";
                    break;
                case VarcharParameterListEnum.Varchar100:
                    par.TypeName = "dbo.Varchar100ParameterList";
                    break;
                case VarcharParameterListEnum.Varchar255:
                    par.TypeName = "dbo.Varchar255ParameterList";
                    break;
                case VarcharParameterListEnum.Varchar510:
                    par.TypeName = "dbo.Varchar510ParameterList";
                    break;
            }

            DataTable dt = new DataTable();
            dt.Columns.Add("textValue", typeof(string));
            par.Value = dt;

            if (values != null)
            {
                foreach (var value in values.Where(p => !string.IsNullOrWhiteSpace(p)))
                {
                    dt.Rows.Add(value);
                }
            }

            return par;
        }

    }