【问题标题】:How to have Entity Framework navigation property query filter in database by default?默认情况下,如何在数据库中拥有实体框架导航属性查询过滤器?
【发布时间】:2013-03-17 02:00:20
【问题描述】:

dbcontext api 似乎将导航属性设置为 ICollections(用于关联的 * 端)。获取可查询对象的正常方法(例如,如果您想要计数)似乎是

int count = dbcontext.Entry(entry).Collection(c => c.navprop).Query().Count();

但如果您想经常在数据库中进行过滤,那会很不方便。更重要的是,它也很容易忘记。如果有人不小心说

int count = entry.navprop.Count();

然后它获取服务器上的所有数据并在那里进行计数,这很慢。

ObjectContext 默认使用的 EntityCollection 类型也是如此。

int count = entry.navprop.CreateSourceQuery().Count();

有没有办法在模型或其他地方设置导航属性的默认集合类型是 IQueryable 或 ObjectQuery 或某种可查询类型?

请注意,这只是导航属性的问题,因为上下文中的实际对象集和数据库集项似乎是可查询的

【问题讨论】:

    标签: c# entity-framework dbcontext objectcontext


    【解决方案1】:

    没有。 IQueryable 不是一个集合; IQueryable 是一个接口,其实现评估针对数据源的查询(集合将是数据源)。

    您可以在加载实体对象时加载计数,但是,如果您不喜欢内联一些无害的方法调用:

    from e in EntityA
    <optional where clause for entity>
    select new
    {
        Entity = e,
        filteredNavPropCount = e.navprop.Where( np => <optional where clause for collection> ).Count()
    }
    

    【讨论】:

    • 虽然我确实发现在导航属性上调用 count 不会在数据库中进行计数,但我确实觉得令人惊讶和烦人,但我更大的问题是人们会看到在 nav 道具上调用 count 有效,即使他们从数据库中提取额外的数据,也不要再想它了。
    • 您可以在要过滤导航属性集合或以某种方式聚合它的地方使用它,而无需从数据库中检索所有实体 - 正如您在问题中所述。
    • ORM 的重点不是高性能,而是易用性。没有什么能比具有自定义结果集的存储过程的性能更好,但这是更多的编码工作。
    • 不会调用 e.navprop.where(whatever).count() 从数据库中获取 e.navprop 中的每个对象吗?
    • 不是在这个例子中 b/c 查询将评估为 SQL 语句并在数据库中执行。
    【解决方案2】:

    我想出了一个解决我大部分问题的解决方案。我最终做的是在我的模型中使用 ObjectContext API,并使需要很长时间才能访问私有的导航属性(用于获取和设置)。您可以通过右键单击 nav 属性在 edmx 文件中执行此操作。

    然后我为包含私有导航属性的类创建了一个部分类文件,并添加了一些类似的内容。

    public ObjectQuery<NavPropType> NavPropName
    {
       get
       {
          if(privateNavProp != null) //in case lazy loading is disabled or something
             return privateNavProp.CreateSourceQuery();
          else
             return null;
       }
    }
    

    现在该类的任何用户都不会意外尝试拉入所有 navprop 项目,其中有很多。并且在 nav 属性上进行查询也很容易,而不必记住每次都调用 CreateSourceQuery。

    我没有添加 setter,因为该导航属性在我的应用程序中是只读的。我确信有一种方法可以制作出适合这种模式的方法,但我对 ObjectContext API 的了解还不够,无法说明如何去做。

    我最终只对可能有大量数据的导航属性执行此操作,因为保留其他属性对性能没有影响。

    编辑:我后来遇到的将其设为私有的一个缺点是我不能再这样做了

    db.EntryTable.OrderBy(e => e.privateNavProp.Count())
    

    即使它足够聪明,不会得到所有实体

    【讨论】:

    • 有谁知道 CreateSourceQuery 是否足够慢,值得拥有一个在第一次调用 getter 时设置并在后续调用中使用的类的私有成员,而不是每次调用 CreateSourceQuery时间?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多