使用实体框架和 .net Core 执行 SP



我使用.net core和实体框架创建了一个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 应仅从数据库返回模型类的约定。

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]");