DbContext.Set().SqlQuery 加载相关实体
本文关键字:加载 SqlQuery 实体 Set DbContext | 更新日期: 2023-09-27 18:34:18
我正在运行以下代码:
var paramUserId = new SqlParameter
{
ParameterName = "userId",
Value = userId
};
string query = string.Format("{0} {1}",
"usp_GetItems",
"@userId");
var results = _context.Set<Item>().SqlQuery(query, paramUserId);
usp_GetItems
是我拥有的存储过程。但是,我的导航属性未加载。有没有办法在实体框架上完成这一点?
因为根据这个问题,在EntityFramework中使用DbContext.Database.SqlQuery进行预先加载看起来是可能的。
谢谢
假设存储过程返回Items
和Users
的非规范化,我想到的一个想法是使用投影DTO来模拟存储过程结果的结构,然后使用SqlQuery
的Context.Database.SqlQuery<T>
风格投影到扁平的DTO中。
然后,您可以使用 LINQ
再次将结果集重新规范化回实体图,我想这是初衷。
详细地
假设 EF 模型中的现有实体:
public class Item
{
public int ItemId { get; set; }
public string Name { get; set; }
}
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
public ICollection<Item> Items { get; set; }
}
创建一个传输 DTO,它表示存储过程结果集的扁平结构:
public class UserItemProcDto
{
public int ItemId { get; set; }
public string ItemName { get; set; }
public int UserId { get; set; }
public string UserName { get; set; }
}
然后投影到非规范化的 DTO 中,最后使用 LINQ 重新规范化:
var results = _context.SqlQuery<UserItemProcDto>(query, paramUserId);
var usersWithItems = results.GroupBy(r => r.UserId)
.Select(g => new User
{
UserId = g.Key,
Name = g.First().UserName,
Items = g.Select(i => new Item
{
ItemId = i.ItemId,
Name = i.ItemName
}).ToList()
});
当然,对于跨多个表的许多存储过程,这显然不是您想要做的事情:)