1

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

我遇到了一个困难的条件场景,在 Web 服务器上的 C# 迭代中更容易解决(在 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 会发挥它的魔力并快速为我提供数据。但是,我正在平衡这与潜在的 v.hard 查询来理解,以及当前具有迭代的出色性能,以及易于理解 C# 方式。

4

2 回答 2

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添加 a 来实现第一部分 ( ) 。.ToList()


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

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

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

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

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

return z.Where(user => user.RoleUserLinks
                           .All(rul => rul.LinkStatusID != linkStatusAdded))
        .ToList();
于 2013-01-09T20:43:11.877 回答