C# 如何实施";“自由形式”;实体框架中的关系6

C# 如何实施";“自由形式”;实体框架中的关系6,c#,.net,entity-framework,C#,.net,Entity Framework,我使用EF6来处理一个构造得有些粗糙的数据库。我使用的是代码优先模型 很多逻辑关系并没有使用键正确实现,而是使用了以前使用复杂SQL查询处理过的各种其他策略(例如,字符分隔的ID或字符串) (更改架构不是一个选项) 我真的想把这些关系作为属性来捕捉。可以通过使用显式查询而不是使用fluent/attribute语法定义实际关系来实现这一点 我计划通过使用执行查询的IQueryable属性来实现这一点。例如: partial class Product { public IQueryabl

我使用EF6来处理一个构造得有些粗糙的数据库。我使用的是代码优先模型

很多逻辑关系并没有使用键正确实现,而是使用了以前使用复杂SQL查询处理过的各种其他策略(例如,字符分隔的ID或字符串)

(更改架构不是一个选项)

我真的想把这些关系作为属性来捕捉。可以通过使用显式查询而不是使用fluent/attribute语法定义实际关系来实现这一点

我计划通过使用执行查询的
IQueryable
属性来实现这一点。例如:

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;
        }
    }
}
部分类积{
公共可查询子类别{
得到{
//SubCategoriesID是一个类似“1234、12351、12”的字符串,包含ID列表。
var id=SubCategoriesID.Split(',).Select(x=>int.Parse(x.Trim());
从此.GetContext().tblCategories中的类别返回
其中id.Contains(category.CategoryID)
选择类别;
}
}
}
(方法是一种扩展方法,它以某种方式获取了适当的
DbContext

然而,有没有更好的方法来做到这一点,我不熟悉

此外,如果我这样做,那么为操作获取
DbContext
的最佳方法是什么?它可以是:

  • 创建一个新的。我对这样做有点怀疑,因为我不太了解它们是如何工作的
  • 使用一些技巧获取用于创建此特定实例的上下文
  • 做点别的吗

  • 首先,我建议不要返回IQueryable,因为它保留了与原始DbContext的关系。相反,我将
    ToList
    查询结果,并将其作为
    IEnumerable

    尽量不要让
    DbContext
    实例挂起;它们中有很多状态管理,而且由于它们不是线程安全的,所以您不希望多个线程访问同一个实例。我个人倾向于遵循的数据访问方法模式是在using块中使用新的
    DbContext

    using (var ctx = new YourDbContextTypeHere()) {
      return (from category in ctx.tblCategories
                where ids.Contains(category.CategoryID)
                select category).ToList();
    }
    

    首先,我建议不要返回IQueryable,因为它保留了与原始DbContext的关系。相反,我将
    ToList
    查询结果,并将其作为
    IEnumerable

    尽量不要让
    DbContext
    实例挂起;它们中有很多状态管理,而且由于它们不是线程安全的,所以您不希望多个线程访问同一个实例。我个人倾向于遵循的数据访问方法模式是在using块中使用新的
    DbContext

    using (var ctx = new YourDbContextTypeHere()) {
      return (from category in ctx.tblCategories
                where ids.Contains(category.CategoryID)
                select category).ToList();
    }
    
    请注意,ID列表中的.Contains()在EF中非常慢,也就是说,请尽量避免使用它。我会使用子查询,例如

    var subcategories = context.SubCategories.Where(...);
    var categories = context.Categories.Where(x => subCategories.Select(x => x.Id).Contains(category.CategoryId);
    
    在此设置中,您可以避免将所有ID加载到服务器上,并且查询速度会很快。

    请注意,ID列表上的.Contains()在EF中非常慢,即尝试避免它。我会使用子查询,例如

    var subcategories = context.SubCategories.Where(...);
    var categories = context.Categories.Where(x => subCategories.Select(x => x.Id).Contains(category.CategoryId);
    

    在这种设置中,您可以避免将所有ID加载到服务器上,查询速度也会很快。

    我看不出这段代码与问题或我的情况有什么关系。由于该列包含ID列表,因此我必须以某种方式处理它。我可以使用
    String.Contains
    ,但我怀疑这会更慢。另外,您是否可以找出
    包含的
    非常慢的语句的来源?我想知道为什么。我认为它只会被映射到一个
    IN
    类语句中。问题是EF不能用参数列表预编译任何东西。您是对的,SQL将在中生成,但是为EF解析表达式树的编译可能非常重要(比SQL查询本身的执行时间长)。每当EF无法预编译时,它的速度就非常慢……我不知道这段代码与问题或我的环境有什么关系。由于该列包含ID列表,因此我必须以某种方式处理它。我可以使用
    String.Contains
    ,但我怀疑这会更慢。另外,您是否可以找出
    包含的
    非常慢的语句的来源?我想知道为什么。我认为它只会被映射到一个
    IN
    类语句中。问题是EF不能用参数列表预编译任何东西。您是对的,SQL将在中生成,但是为EF解析表达式树的编译可能非常重要(比SQL查询本身的执行时间长)。每当EF无法预编译时,它的速度就非常慢。。。