我使用LINQ编写了以下查询通过将行转换为列来旋转数据:
var query = from p in context.PrivilegesTable
group p by p.Type into g
select new Privileges
{
Type = g.Key,
AllowRead = g.Any(p => p.Seq == 1),
AllowAdd = g.Any(p => p.Seq == 2)
AllowEdit = g.Any(p => p.Seq == 3)
AllowDelete = g.Any(p => p.Seq == 4)
};
我认为有更好的方法来实现它。有关详细信息,请阅读以下内容:
我有以下权限表:
Type Seq
1 1
2 1
2 2
3 1
3 2
3 3
以下Privileges类:
class Privileges
{
public int ID { get; set; }
public Type Type { get; set;}
public int AllowRead { get; set; } // when sequence = 1
public int AllowAdd { get; set; } // when sequence = 2
public int AllowEdit { get; set; } // when sequence = 3
public int AllowDelete { get; set; } // when sequence = 4
}
现在,我想使用LINQ创建一个List<Prvileges>
,以获得以下结果:
[Type,AllowRead,AllowAdd,AllowEdit,AllowDelete]
[1,真,假,假,假]
[2,真,真,假,假]
[3,真,真,真,假]
我的查询对性能有害吗? 还有更好的吗?
答案 0 :(得分:0)
我建议使用enum
来表示您可以拥有的权限。
[Flags]
enum Privilege
{
None = 0,
Read = 1,
Add = 2,
Edit = 4,
Delete = 8,
}
通过这种方式,您可以存储单个值来表示您的所有权限。那么你的Privileges类就是这样的:
class Privileges {
public int ID { get; set; }
public Type Type { get; set;}
private Privilege m_Privileges;
public bool AllowRead {
get { return HasPrivilege(Privilege.Read); }
set { CheckPrivilege(Privilege.Read, value); }
}
public bool AllowAdd {
get { return HasPrivilege(Privilege.Add); }
set { CheckPrivilege(Privilege.Add, value); }
}
public bool AllowEdit {
get { return HasPrivilege(Privilege.Edit); }
set { CheckPrivilege(Privilege.Edit, value); }
}
public bool AllowDelete {
get { return HasPrivilege(Privilege.Delete); }
set { CheckPrivilege(Privilege.Delete, value); }
}
private bool HasPrivilege(Privilege p) {
return (m_Privileges & p) == p;
}
private void CheckPrivilege(Privilege p, bool owns) {
if (owns)
m_Privileges = m_Privileges | p;
else
m_Privileges = m_Privileges & (~p);
}
}
当然,只有拥有有限且已知数量的权限,此方法才有效。
希望有所帮助
答案 1 :(得分:0)
您的查询性能将非常糟糕,因为每个Any都会进行连接(L2S实现问题)。在SQL中你会做一个pivot子句。它可以在L2S中模拟但是连接问题仍然存在(我今天在连接上报告了这个错误)。对不起,我的知识没有解决方法。如果perf是个问题,则必须缓存或使用原始sql。
编辑:我想我找到了一个特例来解决你的问题:
var query = from p in context.PrivilegesTable
let shift = 1 << p.Seq
group shift by p.Type into g
select new
{
Type = g.Key,
AllowMask = g.Sum(),
};
那有多酷? ;-)不幸的是它是可怕的代码,只能使用64位标志。