1

在我的 WCF 服务的业务逻辑中,我有一个允许按一个或多个列过滤用户的功能。我做过滤的方式是这样的:

public List<UserDto> GetUsersByFilters    (
                                              String ssn, 
                                              List<Guid> orderIds, 
                                              List<MaritalStatusEnum> maritalStatuses, 
                                              String name, 
                                              int age
                                          )
{
    using (MyProjEntities entities = new MyProjEntities())
    {
        IQueryable<User> users = entities.Users;

        // Filter By SSN (check if the user's ssn matches)
        if (String.IsNullOrEmusy(ssn) == false)
            users = users.Where(us => us.SSN == ssn);

        // Filter By Orders (check fi the user has all the orders in the list)
        if (orderIds != null)
            users = users.Where(us => UserContainsAllOrders(us, orderIds));

        // Filter By Marital Status (check if the user has a marital status that is in the filter list)
        if (maritalStatuses != null)
            users = users.Where(pt => maritalStatuses.Contains((MaritalStatusEnum)us.MaritalStatus));

        // Filter By Name (check if the user's name matches)
        if (String.IsNullOrEmusy(name) == false)
            users = users.Where(us => us.name == name);

        // Filter By Age (check if the user's age matches)
        if (age > 0)
            users = users.Where(us => us.Age == age);


        return users.ToList();
    }
}

private   Boolean   UserContainsAllOrders(User user, List<Guid> orderIds)
{
    return orderIds.All(orderId => user.Orders.Any(order => order.Id == orderId));
}

我的问题是: 数据库上发生了哪些查询以及本地发生了什么?

显然,我不希望每次都将数据库中的所有用户都提取到我的记忆中......

我假设因为“按订单过滤”使用本地函数 - 无法在数据库上完成,所以这是在本地完成的。我对吗 ?

如果是这样 - 这是否意味着之后发生的所有事情也会在本地发生?

如果没有“按订单过滤”怎么办?一切都会在数据库端完成吗?

LINQ-TO-EF 是否知道如何将“婚姻状况”查询“翻译”为数据库端查询?(我正在检查用户的婚姻状况枚举是否存在于传递给函数的枚举列表中)。

谢谢 !

[编辑:对不起。我不知道为什么代码没有自动着色]

4

1 回答 1

1

如果您将鼠标悬停在不同的“where”语句上,您会注意到它们是 IQueryable 的(或者至少它们应该是)......只要您不断将 Iqueryable “where's”附加到彼此,该语句就应该保留一个 Iqueryable (而不是每次都调用数据库)。

当您最终在底部执行 ToList 时,您将真正调用数据库。

实际上,在您构建 linq to ent 语句时观察非常重要,并确保您不会无意中调用返回 IEnumerable 的扩展,而不是您想要的。如果您不小心调用了返回 IEnumerable 的扩展程序,然后开始调用“skip”和“take”,尝试进行 sql 侧分页,那么您将错过......您将跳过并占用内存对象而不是创建优化的 sql 查询。

至于到底发生了什么,如果您打开分析器并观察调用 ToList(或任何其他 IEnumerable 扩展)时提交的 sql 查询,那将是最有趣的。Linq to Ent 通常会构建一个非常优化的 sql 语句。添加一个 Iqueryable Skip and Take 例如,Linq to Ent 将为 RowNumber 和类似的东西生成必要的 sql,以便它可以有效地执行 sql 服务器端分页。(请注意,随着查询变得越来越复杂,Linq to Ent 更难创建最优化的查询。如果复杂的查询开始花费太长时间,最好捕获正在提交的 sql,因为通常可以编写自己的更优化的在这些情况下查询)。

您也可以通过这种方式跟踪 sql

于 2012-06-08T15:52:31.693 回答