如何在实体框架6中实现“自由形式”关系

时间:2016-05-19 12:19:38

标签: c# .net entity-framework

我正在使用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操作的最佳方法是什么?它可能是:

  1. 只需创建一个新的。我对这样做有点怀疑,因为我对他们的工作方式知之甚少。
  2. 使用一些技巧来获取用于创建此特定实例的上下文。
  3. 做点什么吗?

2 个答案:

答案 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加载到服务器上,并且查询速度很快。