我有一个场景,其中角色和客户端存储在表中,我们必须在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
答案 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
)
GroupBy
OrderBy
rowVersion Last
(最高)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);
}
}
}