我正在运行以下代码:
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
是我的一个存储过程。
但是我的导航属性没有被加载。有没有办法在 Entity Framework 上完成这个?
因为根据这个问题Eager loading in EntityFramework with DbContext.Database.SqlQuery看起来这是可能的。
谢谢
最佳答案
假设存储过程返回 Items
的非规范化和 Users
,想到的一个想法是使用一个模拟存储过程结果结构的投影 DTO,然后使用 Context.Database.SqlQuery<T>
SqlQuery
的味道转换到扁平化的 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()
});
对于许多跨越多个表的存储过程,这显然不是您想要做的事情,当然 :)
关于c# - DbContext.Set<T>().SqlQuery 加载相关实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27500989/