通过避免多次输入来为客户计算范围

时间:2019-02-05 03:27:36

标签: c# .net linq dictionary

我有一个场景,其中角色和客户端存储在表中,我们必须在Dictionary中获取它,并且必须确保对于用户而言,没有客户端具有多个角色条目,并且万一它采用了最新的角色RowVersion记录。

在内部表中,我们对用户,角色和客户ID以及数据有独特的约束,如下所示:

#1- User,Role, Client Id, TimeStamp, rowVersion
    201,READ,101, 1/18/2019, 2
    201,WRITE,101, 1/18/2019, 1
    201,ADMIN,102, 1/18/2019, 3
    202,READ,102, 1/19/2019, 12

对于用户201-如果客户端101具有多个角色,则客户端101只能具有一个角色-排序后选择最新版本。 在上面的#1中,它将计算到下面并存储在Dictionary中-

201,READ,101, 1/18/2019, 2
201,ADMIN,102, 1/18/2019, 3

在查询数据并将其存储在Dictionary中时,如何使用LINQ有效地实现这一目标?

编辑 实际上,RowVersion是SQL Server行版本,例如0x0000000000019E12,只是为了简化我添加的数字来显示。

我们需要记住,对于给定的用户,我们正在为此RoleScope计算。在我的示例结果中,用户201的平均值为

201,READ,101, 1/18/2019, 2
201,ADMIN,102, 1/18/2019, 3

我想在LINQ中进行转换的SQL形式的答案

select * from(
select UserId,ClientId,RowVersion,RoleCode,row_number() 
over(partition by ClientId order by RowVersion desc) as roworder
from dbo.UR where UserId=6
) temp
where roworder=1

4 个答案:

答案 0 :(得分:1)

具有以下课程:

class ClientRole
{
    public int ClientId { get; set; }
    public string Role { get; set; }
    public int RowVersion { get; set; }
}

尝试一下:

var clientRoles = new List<ClientRole>
{
    new ClientRole { ClientId = 101, Role = "READ", RowVersion = 2 },
    new ClientRole { ClientId = 101, Role = "WRITE", RowVersion = 1 },
    new ClientRole { ClientId = 102, Role = "ADMIN", RowVersion = 2 },
    new ClientRole { ClientId = 102, Role = "OTHER", RowVersion = 12 }
};

var clientRolesDic = (
    from cr in clientRoles
    group cr by cr.ClientId into g
    select g.OrderByDescending(i => i.RowVersion).First()
    )
    .ToDictionary(k => k.ClientId);

答案 1 :(得分:1)

如果我了解您的需求。并假设rowversion只是一个int(而不是SqlServer timeStamp

  1. 使用GroupBy
  2. OrderBy rowVersion
  3. 选择Last(最高)
  4. ToDictionary

示例

var results = list.GroupBy(x => x.ClientId)
                  .Select(x => x.OrderBy(y => y.rowVersion).Last())
                  .ToDictionary(x => x.ClientId);

答案 2 :(得分:1)

看起来像一个简单的查询:

var clientRoles = new []
{
    new { ClientId = 101, Role = "READ", RowVersion = 2 },
    new { ClientId = 101, Role = "WRITE", RowVersion = 1 },
    new { ClientId = 102, Role = "ADMIN", RowVersion = 3 },
    new { ClientId = 102, Role = "READ", RowVersion = 2 },
};

var result =
    from cr in clientRoles
    orderby cr.ClientId, cr.RowVersion descending
    group cr by cr.ClientId into gs
    from g in gs.Take(1)
    select g;

这仅返回以下行:

    new { ClientId = 101, Role = "READ", RowVersion = 2 },
    new { ClientId = 102, Role = "ADMIN", RowVersion = 3 },

似乎您的源数据有错误-最后一行的RowVersion应该是2,而不是12

答案 3 :(得分:0)

万一Fiddle Stop这里停止工作是FULL正常工作的解决方案,包括上面Randall提出的建议。

using System;
using System.Linq;
public class Simple {
  public static void Main() {
            var userRoles = (new[] 
            { 
            new { clientid=1 , rowVersion = 1 , role="READ" },
            new { clientid=1 , rowVersion = 2 , role="EDIT" },
            new { clientid=2 , rowVersion = 3 , role="ADMIN" },
            new { clientid=1 , rowVersion = 4 , role="VIEW" }
        });

var o = userRoles.OrderByDescending(x => x.rowVersion)
                .GroupBy(x => x.clientid)
                .SelectMany(g =>
                   g.Select((j, i) => new { j.rowVersion, j.role, rn = i + 1 })
                   );

    var z =  o.Select(x => new {x.rowVersion, x.role, x.rn}).Where(a => a.rn==1);

      var results = userRoles.GroupBy(x => x.clientid)
                  .Select(x => x.OrderByDescending(y => y.rowVersion).First());

          Console.WriteLine("Solution #1");

        foreach (var i in z)
        {
            Console.WriteLine("{0} {1} {2}", i.rowVersion, i.role, i.rn);
        }

      Console.WriteLine("Solution #2");

      foreach (var k in results)
        {
            Console.WriteLine("{0} {1}", k.rowVersion, k.role);
        }

  }
  }