我正在使用EF 6来处理一个有点粗糙的数据库。我正在使用代码优先模型。
许多逻辑关系没有使用键正确实现,而是使用以前使用复杂SQL查询操作的各种其他策略(例如字符分隔的id或字符串)。
(无法更改架构)
我真的想将这些关系捕获为属性。可以通过使用显式查询而不是使用fluent / attribute语法定义实际关系来完成此操作。
我打算通过执行查询的IQueryable<T>
属性来执行此操作。例如:
partial class Product {
public IQueryable<tblCategory> SubCategories {
get {
//SubCategoriesID is a string like "1234, 12351, 12" containing a list of IDs.
var ids = SubCategoriesID.Split(',').Select(x => int.Parse(x.Trim()));
return from category in this.GetContext().tblCategories
where ids.Contains(category.CategoryID)
select category;
}
}
}
(GetContext()
方法是一种扩展方法,以某种方式获取适当的DbContext
)
然而,是否有更好的方法可以做到这一点,我不熟悉?
此外,如果我这样做,获得DbContext
操作的最佳方法是什么?它可能是:
答案 0 :(得分:1)
首先,我建议不要返回IQueryable,因为它保留了与原始DbContext的关系。相反,我ToList
查询结果并将其作为IEnumerable<tblCategory>
尽量不让DbContext
个实例闲置;很多状态管理都融入其中,因为它们不是线程安全的,所以你不想让多个线程碰到同一个实例。我个人倾向于遵循数据访问方法的模式是在使用块中使用新的DbContext
:
using (var ctx = new YourDbContextTypeHere()) {
return (from category in ctx.tblCategories
where ids.Contains(category.CategoryID)
select category).ToList();
}
答案 1 :(得分:1)
请注意,在EF列表上的.Contains()在EF中非常慢,即尽量避免它。我使用子查询,例如
var subcategories = context.SubCategories.Where(...);
var categories = context.Categories.Where(x => subCategories.Select(x => x.Id).Contains(category.CategoryId);
在此设置中,您可以避免将所有ID加载到服务器上,并且查询速度很快。