基本上我有一些与此类似的数据表
| ItemId | RuleId | IsActive |
------------------------------
| ItemA | RuleA | FALSE |
------------------------------
| NULL | RuleA | TRUE |
------------------------------
| ItemC | RuleA | TRUE |
------------------------------
| ItemA | RuleB | FALSE |
------------------------------
| NULL | RuleB | TRUE |
------------------------------
我希望得到这样的结果
表示项目
| ItemId | RuleId | IsActive |
------------------------------
| ItemA | RuleA | FALSE |
------------------------------
| ItemA | RuleB | FALSE |
------------------------------
表示项目b
| ItemId | RuleId | IsActive |
------------------------------
| NULL | RuleA | TRUE |
------------------------------
| NULL | RuleB | TRUE |
------------------------------
表示项目c
| ItemId | RuleId | IsActive |
------------------------------
| ItemC | RuleA | TRUE |
------------------------------
| NULL | RuleB | TRUE |
------------------------------
基本上如果有特定规则,则使用指定的,否则使用默认规则设置为null作为itemId
如何在linq中实现这一目标?
提前致谢
编辑:感谢造型,@ lazyberezovsky。 @dasblinkenlight我也没有sql的查询。我确实需要以linq方式,但如果有人能给我一些建议如何以sql方式获得结果,那也很有帮助。
答案 0 :(得分:1)
这不是最漂亮的LINQ查询,但这里有一个完整的代码示例
//the sample data as provided by the OP
var rules = new []
{
new { ItemId = "ItemA", RuleId = "RuleA", IsActive = false },
new { ItemId = (string)null, RuleId = "RuleA", IsActive = true },
new { ItemId = "ItemC", RuleId = "RuleA", IsActive = true },
new { ItemId = "ItemA", RuleId = "RuleB", IsActive = false },
new { ItemId = (string)null, RuleId = "RuleB", IsActive = true },
};
//the items that we want to get the rules for
var items = new [] { "ItemA", "ItemB", "ItemC", };
//get the rules for all of the items
var query = from i in items
let itemRules = from r in rules
//we need to prefer rules that match our id
orderby r.ItemId ?? "" descending
//match on id or null
where (r.ItemId ?? i) == i
group r by r.RuleId into grouping
//take the best match
select grouping.First()
select new
{
i,
itemRules,
};
这是输出
我认为这不适用于LINQ to SQL,但它肯定适用于LINQ to Objects。当我有时间构建测试数据库时,我会看看是否可以使用LINQ to SQL的版本。
答案 1 :(得分:0)
您可以在LINQ中使用任何语言构造(它不会被称为语言集成查询)。例如,如果您使用VB.NET - 您可以直接在LINQ查询
中使用CHOOSE
function
答案 2 :(得分:0)
您可以按RuleId
对所有项目进行分组,然后从每个组中选择第一项,该项目已指定itemId
。如果没有这样的项目,则创建并返回默认项目:
from i in items
group i by i.RuleId into g
select g.FirstOrDefault(x => x.ItemId == itemId) ??
new Item { ItemId = null, RuleId = g.Key, IsActive = true }
此查询将用于内存中的项目。但是您无法在服务器端创建新的默认项目 - 您将收到错误
无法构造实体或复杂类型“Item” 在LINQ to Entities查询中。
因此,返回匿名类型而不是项目,并在内存中构造项目:
(from i in context.Items
group i by i.RuleId into g
let item = g.FirstOrDefault(x => x.ItemId == itemId)
select new
{
ItemId = item == null ? null : itemId, // default if not found
RuleId = g.Key,
IsActive = item == null ? true : item.IsActive
})
.AsEnumerable() // move to memory
.Select(i => new Item {
ItemId = i.ItemId,
RuleId = i.RuleId,
IsActive = i.IsActive
});
适用于EF。