在这种情况下,可以构建单个LINQ查询表达式吗?

时间:2009-09-17 02:35:28

标签: c# join linq-to-objects query-expressions

我面临的情况是我必须根据许多对象过滤单个对象。

为了举例,我有一个 Grocery 对象,它包含Fruit和Vegetable属性。然后我有个人水果蔬菜对象。

我的目标是:

var groceryList = from grocery in Grocery.ToList()
                  from fruit in Fruit.ToList()
                  from veggie in Vegetable.ToList()
                  where (grocery.fruitId = fruit.fruitId)
                  where (grocery.vegId = veggie.vegId)
                  select (grocery);

我遇到的问题是水果和蔬菜对象是空的。 如果为空,我的意思是他们的列表计数为0,我只想在填充过滤器列表时应用过滤器。

我也 NOT 能够使用像对象为空的东西:

var groceryList = from grocery in Grocery.ToList()
                  from fruit in Fruit.ToList()
                  from veggie in Vegetable.ToList()
                  where (grocery.fruitId = fruit.fruitId || fruit.fruitId == String.Empty)
                  where (grocery.vegId = veggie.vegId || veggie.vegId == String.Empty)
                  select (grocery);

所以,我打算检查 Fruit 蔬菜列表计数...并在连续过滤的 Grocery 对象上将它们过滤为单独的表达式

但是,如果在单个查询表达式中出现空对象,是否还有一种方法可以获取列表?

5 个答案:

答案 0 :(得分:0)

尝试以下内容:

var joined = grocery.Join(fruit, g => g.fruitId,
                                 f => f.fruitId,
                                 (g, f) => new Grocery() { /*set grocery properties*/ }).
                Join(veggie, g => g.vegId,
                             v => v.vegId,
                             (g, v) => new Grocery() { /*set grocery properties*/ });

我已经说过设置杂货店属性,您可以从选择器的g,f,v变量设置杂货对象的属性。有意义的是设置g.fruitId = f.fruitIdg.vegeId = v.vegeId

答案 1 :(得分:0)

认为 LINQ GroupJoin operator会帮助你。它类似于TSQL LEFT OUTER JOIN

答案 2 :(得分:0)

IEnumerable<Grocery> query = Grocery

if (Fruit != null)
{
  query = query.Where(grocery =>
    Fruit.Any(fruit => fruit.FruitId == grocery.FruitId));
}

if (Vegetable != null)
{
  query = query.Where(grocery =>
    Vegetable.Any(veggie => veggie.VegetableId == grocery.VegetableId));
}

List<Grocery> results = query.ToList();

答案 3 :(得分:0)

var groceryList =
  from grocery in Grocery.ToList()
  join fruit in Fruit.ToList()
       on grocery.fruidId equals fruit.fruitId
       into groceryFruits
  join veggie in Vegetable.ToList()
       on grocery.vegId equals veggie.vegId
       into groceryVeggies
  where ... // filter as needed
  select new
  {
    Grocery = grocery,
    GroceryFruits = groceryFruits,
    GroceryVeggies = groceryVeggies
  };

答案 4 :(得分:0)

您必须使用左外连接(如SQL)。在查询下面的技巧

private void test()
{
    var grocery = new List<groceryy>() { new groceryy { fruitId = 1, vegid = 1, name = "s" }, new groceryy { fruitId = 2, vegid = 2, name = "a" }, new groceryy { fruitId = 3, vegid = 3, name = "h" } };
    var fruit = new List<fruitt>() { new fruitt { fruitId = 1, fname = "s" }, new fruitt { fruitId = 2, fname = "a" } };
    var veggie = new List<veggiee>() { new veggiee { vegid = 1, vname = "s" }, new veggiee { vegid = 2, vname = "a" } };
    //var fruit= new List<fruitt>();
    //var veggie = new List<veggiee>();

    var result = from g in grocery
                 join f in fruit on g.fruitId equals f.fruitId into tempFruit
                 join v in veggie on g.vegid equals v.vegid into tempVegg
                 from joinedFruit in tempFruit.DefaultIfEmpty()
                 from joinedVegg in tempVegg.DefaultIfEmpty()
                 select new { g.fruitId, g.vegid, fname = ((joinedFruit == null) ? string.Empty : joinedFruit.fname), vname = ((joinedVegg == null) ? string.Empty : joinedVegg.vname) };

    foreach (var outt in result)
        Console.WriteLine(outt.fruitId + "  " + outt.vegid  + "  " + outt.fname  + "  " + outt.vname);
}
public class groceryy
{
    public int fruitId;
    public int vegid;
    public string name;
}
public class fruitt
{
    public int fruitId;
    public string fname;
}
public class veggiee
{
    public int vegid;
    public string vname;
}

修改 这是样本结果

1 1 s s

2 2 a a

3 3