我想知道这样的事情是否可以完成(当然我所写的内容不起作用,但这正是我本来想要实现的目标)。
var test = u.Owner;
a.Table.Where(u => test == true)
我有一个我要重用的linq查询(基本上我得到了一个我使用了5次的查询),唯一改变的是我正在比较的内容。
所以在上面的u.Owner与真实比较。在另一个查询中,它看起来是一样的,但不是u.Owner,我可能有u.Add == true或u.Edd == true。
有没有一种方法可以重用我所拥有的东西。当然,在我的代码中,查询有点长,但我只是缩短了。
修改
基本上是整个查询
List<Permission> clearence = user.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner)).ToList();
permissionNeeded == Enum
所以我的原始方式是u.Permission.Name == permissionNeeded
所以我将枚举值与字符串进行了比较。
现在我的数据库模型已经发生变化,我需要分别检查5个不同的权限,这些权限是bool而不是字符串。
u.Add = true || u.Owner == true;
u.Edit = true || u.Owner == true;
u.Delete= true || u.Owner == true;
u.View= true || u.Owner == true;
这是整个查询的所有更改,这就是为什么我想把它变成一个查询(就像我以前一样)。
所以我想有一个switch语句。该方法仍然接受permissionNeeded(enum)然后我会查看我需要的子句以及如何将其插入查询中。
switch(PermssionNeeded)
{
case PermissionTypes.Add:
u.Add;
break;
// all other cases here.
}
答案 0 :(得分:4)
利用Where
可以使用类型Table
作为参数的任何函数并返回布尔值来创建类似函数的事实:
public IQueryable<Table> QueryTables(Func<Table, bool> testFunction)
{
return a.Table.Where(testFunction).AsQueryable<Table>();
}
编辑(除了编辑以添加上面的AsQueryable,我之前忘记了)
如果 all 你要做的是改变测试中使用的布尔字段,你不想指定一个完整的函数(你要发现的很多)更容易),你需要使用一些反思:
using System.Reflection;
public IQueryable<Table> QueryTables(PropertyInfo pi)
{
return a.Table.Where(t => (bool)(pi.GetGetMethod().Invoke(t, null))).AsQueryable<Table>();
}
要构造PropertyInfo
对象,请使用以下内容:
PropertyInfo pi = typeof(Table).GetProperty("Owner");
我更喜欢早期的方法,但我确实想表明这样的事情至少是可能的。
答案 1 :(得分:3)
如果您只想指定要检查的属性,可以执行
public IEnumerable<Table> GetTables(Func<Table,bool> getValue)
{
return a.Table.Where(table => /*some common filter*/)
.Where(table => getValue(table))
}
答案 2 :(得分:1)
var query = from u in uSrc join v in vSrc on u.ID equals v.RelatedUID
where v.Valid && u.Created < DateTime.UtcNow.AddDays(-365)
select u; // relatively complicated starting point.
var q1 = query.Where(u => u.Add); // must also have Add true
var q2 = query.Where(u => u.Test); // must also have Test true
var q3 = query.Where(u => u.ID < 50); // must also have ID < 50
等等。
编辑:
好的,所以你的初始查询是:
List<Permission> clearence = student.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner)).ToList();
但请注意,这会创建一个列表,因此对其进行的任何进一步工作都将是Linq-to-objects的问题。我们将在一分钟内回到这一点,因为它有时是好的,有时不是。
现在,如果我理解正确,您需要针对不同情况使用不同的集合,您可以按照以下方式对查询进行处理:
var set0 = clearance.Where(u.Add = true || u.Owner == true);
var set1 = clearance.Where(u.Edit = true || u.Owner == true);
var set2 = clearance.Where(u.Delete= true || u.Owner == true);
var set3 = clearance.Where(u.View= true || u.Owner == true);
现在,这个将工作,但可能不是最好的方法。如果我们回到原始查询,我们不必执行ToList()
,但可以:
IQueryable<Permission> clearence = student.PermissionLevels.Where(u => u.Id == Id &&( u.Add == permissionNeeded || u.Permission.Name == PermissionTypes.Owner));
现在,在第一种情况下,因为我们构建了一个列表,我们首先获得了与支持的critera匹配的所有值,然后将其存储在内存中clearance
。
在第二种情况下,clearance
根本不存储任何值,而是指示如何获取它们。
问题是哪个更好用。在我们最终将使用第一个查询返回的绝大多数对象的情况下,使用列表版本会有性能提升,因为它们只被加载到内存中一次,然后被占用从内存中没有再次访问数据库。
但是,在大多数情况下,最好是做第二个版本有两个原因:
var trimmed = from set0 select new{u.Id, u.Permission.Name};
我们检索具有Id和Name属性的匿名对象,这些对象是我们关心特定情况的所有内容,并不是从数据库或其他来源检索所有相关字段。
答案 3 :(得分:0)
我最近更喜欢使用Dictionary而不是switch语句。您可以将所有lambas存储在Dictionary<PermissionNeeded, Func<User, bool>>
中,如下所示:
Dictionary<PermissionNeeded, Func<User, bool>> Permissions =
new Dictionary<PermissionNeeded, Func<User, bool>> {
{ PermissionNeeded.Add, u => u.Add }, // don't need to specify == true
{ PermissionNeeded.Edit, u => u.Edit },
...
etc
};
你会这样称呼它:
var clearance = Permissions[PermissionNeeded.Add](user);
或者
var clearance = Permissions[PermissionNeeded.Add](user) && Permissions[PermissionNeeded.Edit](user);
或者
var clearance = Permission[PermissionNeeded.Add](user) || Permissions[PermissionNeeded.View](user);
等等。即使你没有用户对象,我认为这仍然是有效的,并使代码非常容易阅读,如果你必须修改你的功能,它在字典中全部......