实体框架查询:这里的封面下发生了什么?

时间:2014-05-23 00:11:09

标签: c# .net linq entity-framework

我有以下代码。

var category = Office.Categories.FirstOrDefault(c => c.Description == name);

Office是之前读过的Framework Entity对象。

即使我的数据库使用不区分大小写的字符串比较,并且除了大小写之外,其中一个项目完全匹配,此代码返回null

我对这里发生的事情的理解是Office.Categories返回所有相关的行,然后通过常规LINQ搜索这些行,这是区分大小写的。

如果是这样,那是非常低效的,因为我只想返回符合我条件的行。

有人能证实我对此的理解吗?是否可以强制过滤在SQL中进行,这样我就不需要返回我不感兴趣的行? (文本比较将不区分大小写?)

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

如果你已经加载了Office对象(也取决于延迟加载,但假设你不在上下文中)那么你基本上是在做一个区分大小写的linq-to-object查询。如果你想做linq-to-sql那么你应该采取不同的方式,例如:

context.Offices.FirstOrDefault(o=>o.OfficeId == someId)
                  .Categories.FirstOrDefault(c => c.Description == name);

context.Categories.FirstOrDefault(c => c.OfficeId == Office.OfficeId 
                                    && c.Description == name);

答案 1 :(得分:1)

正确,所以你不能:

  • 如果使用延迟加载,则调用Categories属性getter,因为这会导致EF从数据库中检索完整的类别列表

  • 使用预先加载,因为这也会导致从数据库加载完整的类别列表

为避免这种情况,您可以使用以下代码(来自此答案:Using CreateSourceQuery in CTP4 Code First

    public ObjectQuery<T> CreateNavigationSourceQuery<T>(object entity, string navigationProperty)
    {
        var ose = this.ObjectContext.ObjectStateManager.GetObjectStateEntry(entity);
        var rm = this.ObjectContext.ObjectStateManager.GetRelationshipManager(entity);

        var entityType = (EntityType)ose.EntitySet.ElementType;
        var navigation = entityType.NavigationProperties[navigationProperty];

        var relatedEnd = rm.GetRelatedEnd(navigation.RelationshipType.FullName, navigation.ToEndMember.Name);

        return ((dynamic)relatedEnd).CreateSourceQuery();
    }

将它添加到您的上下文并调用它来创建一个ObjectQuery ..您可以在此调用FirstOrDefault,它不会从数据库中检索所有实体:

var category = context.CreateNavigationSourceQuery<Category>(Office, "Categories").FirstOrDefault(c => c.Description == name);