使用Entity Framework和.net Core执行SP

时间:2018-10-03 08:52:22

标签: entity-framework asp.net-core asp.net-core-webapi

我使用.net核心和实体框架创建了一个Web api项目。 它使用一个存储过程,该存储过程返回由实体框架定义的数据库表的大多数属性。

实体framwrok不会带回表的所有列。当我调用api时抱怨我抱怨,当我使用,执行存储过程时找不到找不到的列,

_context.Set<TableFromSql>().FromSql("execute dbo.spr_GetValue").ToList();

我创建了另一个模型类,该类定义了从SP(称为NewClass)带来的属性。

_context.Set<NewClass>().FromSql("execute dbo.spr_GetValue").ToList();

这可行,但是只是想检查是否有SP只能从数据库返回模型类的约定。

1 个答案:

答案 0 :(得分:1)

  

SQL查询必须返回实体或查询类型的所有属性的数据

由于此限制,是在将sql查询结果映射到Model时引起的。它遍历模型中的属性,并尝试从查询结果中检索值。如果query result中不存在模型属性,则会引发错误。

如果要返回所需的列而不是所有列,则一种选择是用Query定义返回的模型。

对于演示代码,您可以在OnModelCreating中进行定义。

builder.Query<TableFromSql>();

注意,为此,您需要确保TableFromSql中的所有属性都存在于execute dbo.spr_GetValue中。

以另一种方式,您可以实现自己的FromSql,这将添加条件以检查查询结果中是否存在属性。

    public static class DbContextExtensions
{
    public static List<T> RawSqlQuery<T>(this DbContext context,string query)
    {
        using (var command = context.Database.GetDbConnection().CreateCommand())
        {
            command.CommandText = query;
            command.CommandType = CommandType.Text;

            context.Database.OpenConnection();

            using (var result = command.ExecuteReader())
            {
                var entities = new List<T>();

                return DataReaderMapToList<T>(result);
            }
        }
    }
    public static List<T> DataReaderMapToList<T>(IDataReader dr)
    {
        List<T> list = new List<T>();
        T obj = default(T);
        while (dr.Read())
        {
            obj = Activator.CreateInstance<T>();
            foreach (PropertyInfo prop in obj.GetType().GetProperties())
            {
                if (ColumnExists(dr, prop.Name))
                {
                    if (!object.Equals(dr[prop.Name], DBNull.Value))
                    {

                        prop.SetValue(obj, dr[prop.Name], null);
                    }
                }
            }
            list.Add(obj);
        }
        return list;
    }
    public static bool ColumnExists(IDataReader reader, string columnName)
    {

        return reader.GetSchemaTable()
                     .Rows
                     .OfType<DataRow>()
                     .Any(row => row["ColumnName"].ToString() == columnName);
    }
}

使用上面的代码,例如:

        var result = _context.RawSqlQuery<ToDoItemVM>("execute [dbo].[get_TodoItem]");