我使用.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只能从数据库返回模型类的约定。
答案 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]");