【问题标题】:Linq complex - Enumeration PerformanceLinq complex - 枚举性能
【发布时间】:2013-01-09 20:29:15
【问题描述】:

有一个返回 IEnumerable<User> 的方法,我一直在使用 Linq / Entity Framework / SQL Server 来返回结果。

我遇到了一个困难的条件 scenario,这在 C# 迭代 Web 服务器上更容易解决(在 linq 语句链的末尾,就在将数据返回给客户端之前):

public IEnumerable<User> ReturnUsersNotInRoles()
{
    IQueryable<User> z = (from users
                    //...many joins..conditions...
                    ).Distinct().Include(x => x.RoleUserLinks).ToList()


    IEnumerable<User> list = new List<User>();

    foreach (User user in z)
    {
        bool shouldReturnUser = true;

        foreach (var rul in user.RoleUserLinks)
        {
            if (rul.LinkStatusID == (byte)Enums.LinkStatus.Added)
                shouldReturnUser = false;
        }
        if (shouldReturnUser)
            list.Add(user);
    }

    return list;
}

问题:在 C# 中是否有一种性能更高/内存开销更少的方法?

我只是从 Linq 带回我需要的实体。没有N+1 场景。目前的表现非常出色。

我意识到理想情况下我会在 SQL/Linq 中编写它,因为这样 SQL Server 会发挥它的魔力并快速为我提供数据。但是,我正在平衡这与潜在的难以理解的查询,以及当前具有迭代的出色性能,以及易于理解 C# 方式。

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    这个怎么样:

    public IEnumerable<User> ReturnUsersNotInRoles()
    {
        var z = (from users
                        //...many joins..conditions...
                        ).Distinct().Include(x => x.RoleUserLinks);
    
        var addedLinkStatusID = (int)Enums.LinkStatus.Added;
        return z.Where(user => 
                   false == user.RoleUserLinks.Any(link => link.LinkStatusID == addedLinkStatusID))
                .ToList();
    }
    

    这应该完全作为 SQL 查询运行 - 您可以通过在定义它的行末尾添加 .ToList() 来实现第一部分 (z)。


    顺便说一句,关于您的问题“在 C# 中是否有更高性能/更少内存开销的方式来执行此操作?” - 好吧,首先您可以在设置shouldReturnUser = false; 后立即添加break 语句。

    其次,无论我是否使用数据库,我都更喜欢尽可能使用 LINQ 原语:

    1. 如果使用得当,使用 LINQ 方法的实现可能会比您编写的任何东西都快或快。
    2. 更重要的是,它们促进了功能性、无状态编程,而不是有状态、容易出错的编程。
    3. 此外,如果您正在使用数据库,您可以决定是否希望代码作为 SQL 查询运行 - 您所要做的就是决定在哪里运行实现。

    【讨论】:

    • 谢谢 sinelaw。同意你的所有观点。特别感谢您看到如何在 linq 中执行此操作 - 能够以简单的功能方式表达真是太好了!
    【解决方案2】:

    您的循环等同于以下 LINQ 查询 - 我发现它比循环更容易理解,并且当与查询的第一部分结合使用时,它允许在服务器上完整执行。

    var linkStatusAdded = (Byte)Enums.LinkStatus.Added;
    
    return z.Where(user => user.RoleUserLinks
                               .All(rul => rul.LinkStatusID != linkStatusAdded))
            .ToList();
    

    【讨论】:

    • 谢谢丹尼尔 - 赞赏。
    猜你喜欢
    • 2011-03-16
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多