2012-07-10 68 views
1

假设你有一个ID列表:LINQ LEFT JOIN与列表<String>

string str = "82174F2000000, 82174F2000001, 82174F2000002, 82174F2000003, 82174F2000004, 82174F2000005"; 

而且你这样做:

var tids = new List<string>(str.Replace(", ", ",").Split(',')); 
var tntable = tids.AsQueryable(); 

而且要将其与左比较表中加入:

var line = from c in db.Ctable 
join l in tntable on c.CarID equals l.CarID into c_j 
    from l in c_j.DefaultIfEmpty() 
    select new 
    { 
Name = c.OwnerName, 
Hours = c.Hours 
    }; 

看起来像tntable没有名为'CarID'的字段。

有人可以帮忙吗?

这是针对LINQ to Entity的。

我已经看到了这一点:

How to compare List<String> to DB Table using LINQ

但不知道做一个LEFT JOIN。

TIA!

我知道这很长;但感谢阅读。

更新的MichaC:

在CTable的数据库中,我们有这些CarIDs:

CarID 
_____ 
82174F2000000 
82174F2000001 
82174F2000002 
82174F2000003 

让我们只说表(tntable)含有分解成记录的字符串:

CarID 
_____ 
82174F2000000 
82174F2000001 
82174F2000002 
82174F2000003 
82174F2000004 
82174F2000005 

所以,一个左加入像这样:

SELECT C.CarID, T.CarID 
FROM CTable C 
LEFT JOIN tntable T ON C.CarID = T.CarID 

会产生你:

T.CarID   C.CarID 
_______   _______ 
82174F2000000 82174F2000000 
82174F2000001 82174F2000001 
82174F2000002 82174F2000002 
82174F2000003 82174F2000003 
82174F2000004 NULL 
82174F2000005 NULL 

回答

1

如果我读你的问题的权利,它看起来像你想的基于ID的列表来过滤,不执行左连接。我认为你想要这样的事情:

var line = from c in db.Ctable 
      where tntable.Contains(c.CarID) 
      select new 
      { 
       Name = c.OwnerName, 
       Hours = c.Hours 
      }; 

更新:您可以将包含检查移动到select语句以返回所有内容。

var line = from c in db.Ctable 
      select new 
      { 
       IsMatch = tntable.Contains(c.CarID), 
       Name = c.OwnerName, 
       Hours = c.Hours 
      }; 

更新2:好的这个怎么样。使用我的原始从SQL中提取相关项目,然后使用Linq到对象来按照自己想要的方式实际构建列表。 .ToList()强制它进行SQL查询。你也可以使用.AsEnumerable()。

var filtered = from c in db.Ctable 
      where tntable.Contains(c.CarID) 
      select new 
      { 
       CarID = c.CarID, 
       Name = c.OwnerName, 
       Hours = c.Hours 
      }; 

var line = from x in tntable 
      join i in filtered.ToList() on x equals u.CarID into i_match 
      from i in i_match.DefaultIfEmpty() 
      select { x, i }; 
+0

我不仅想知道CTable中的内容,而且还想返回NULL(不在CTable中)。你有的例子只返回CTable中的内容。谢谢! – scv 2012-07-10 00:46:54

+0

如果它有效,它非常酷。我会立即尝试并报告。 – scv 2012-07-10 21:36:35

+0

看起来你有很好的chakara。再次感谢。 – scv 2012-07-10 23:29:46

0

从您发表评论希望NULL还是选择即使ID不在ctable发现在tntable每个ID的对象?如果我理解正确的话,我相信这会给你想要的效果。

var desired = from l in tntable 
       join c in ctable on l equals c.CarID into lj 
       from c in lj.DefaultIfEmpty() 
       select 
        new 
         { 
          Name = c == null ? null : c.OwnerName, 
          Hours = c == null ? (int?)null : c.Hours 
         }; 
+0

错误是'l.CarID'b/c tntable没有名为'CarID'的字段。所以我想我必须创建一个名为'CarID'的字段的Model(类),然后执行列表 table2 = new List ();然后将字符串中的每个值添加到它中。这有意义吗?谢谢! – scv 2012-07-10 01:32:40

+0

啊我是测试这与LINQ到对象,它在那里工作很好,我不能再现您创建数据库模型时出现的特定错误我得到的错误更加神秘(此方法支持LINQ to Entities基础结构,并且不打算直接从你的代码中使用)。我显然不太了解Entity Framework来提供您的答案。抱歉。 – vossad01 2012-07-10 02:10:55

+0

感谢vossad01甚至尝试;但你知道我喜欢你的NULL。再次感谢。 – scv 2012-07-10 02:57:20

0

在此看一看:

string str = "Pat, Boots"; 
var names = new List<string>(str.Replace(", ", ",").Split(',')).AsQueryable(); 

Pet defaultPet = new Pet { Name = "Default Pet", Age = -1 }; 

List<Pet> pets1 = new List<Pet>{ 
      new Pet { Name="Barley", Age=8 }, 
      new Pet { Name="Boots", Age=4 }, 
      new Pet { Name="Whiskers", Age=1 } 
    }; 

var pets = from name in names 
      join pet in pets1 on name equals pet.Name into gj 
      from subpet in gj.DefaultIfEmpty(defaultPet) 
      select new { Name = name, Age = subpet.Age }; 


foreach(var newPet in pets) { 
    Console.WriteLine("\nName: {0}, Age: {1} ", newPet.Name, newPet.Age); 
} 

这将产生:

Name: Pat, Age: -1 
Name: Boots, Age: 4 

如果不这样做你想要什么,然后有在How to: Perform Left Outer Joins (C# Programming Guide) on MSDN仔细看看。

我对DefaultIfEmpty()使用了上面的链接和MSDN的帮助页面。

+0

谢谢泰米克。我不在一台可以运行你的例子的电脑上;但它看起来可以用于链接到对象。你有没有试图查询一个数据库中的表,并留下连接到一个字符串(非数据库)?我很确定这是一个非常普遍的任务。用户键入一堆文本,并确定它们是否在表格中。谢谢! – scv 2012-07-10 09:06:54

+0

如果你去MSDN论坛并在linq +上进行搜索+实体+左+加入+字符串或LINQ +到+实体+字符串,你会得到1帖子。 – scv 2012-07-10 18:05:50