Linq complex - 枚举性能

时间:2013-01-09 20:29:16

标签: c# linq

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

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

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会发挥它的魔力并快速为我提供数据。但是,我正在通过潜在的v.hard查询来平衡这一点,以及当前迭代的优异性能,以及理解C#方式的简便性。

2 个答案:

答案 0 :(得分:2)

这个怎么样:

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查询运行 - 您可以通过在定义它的行的末尾添加z来实现第一部分(.ToList())。


顺便说一下,关于你的问题“在C#中有更高性能/更少的内存开销方式吗?” - 首先,您可以在设置break后立即添加shouldReturnUser = false;语句。

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

  1. 如果使用正确,使用LINQ方法的实现可能会比您编写的任何内容快或快。
  2. 更重要的是,他们在有状态,容易出错的编程上推广功能性,无状态编程。
  3. 此外,如果 使用数据库,您可以决定是否希望代码作为SQL查询运行 - 您只需决定在哪里实现。

答案 1 :(得分:0)

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

var linkStatusAdded = (Byte)Enums.LinkStatus.Added;

return z.Where(user => user.RoleUserLinks
                           .All(rul => rul.LinkStatusID != linkStatusAdded))
        .ToList();