1

基本上我有一些类似的数据表

| ItemId | RuleId | IsActive |
------------------------------
| ItemA  | RuleA  | FALSE    |
------------------------------
| NULL   | RuleA  | TRUE     |
------------------------------
| ItemC  | RuleA  | TRUE     |
------------------------------
| ItemA  | RuleB  | FALSE    |
------------------------------
| NULL   | RuleB  | TRUE     |
------------------------------

我想得到这样的结果

对于项目 a

| 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 方式获得结果,它也会有很大帮助。

4

3 回答 3

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 一起使用的版本。

于 2013-05-30T16:44:05.510 回答
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 }

此查询将适用于内存中的项目。但是你不能在服务器端创建新的默认项目 - 你会收到一个错误

无法在 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。

于 2013-05-30T16:39:17.797 回答
0

您可以在 LINQ 中使用任何语言构造(它不被称为语言集成查询)。例如,如果您使用 VB.NET - 您可以直接在 LINQ 查询中使用CHOOSE函数

于 2013-05-30T16:34:58.550 回答