0

我正在尝试找到一种更好的方法来使用 LINQ 和 Lambda 表达式编写有效的 JOIN,希望使用 Join 来处理以下类型:

public class Patent
{
    public string Title { get; set; }
    public string YearOfPublication { get; set; }
    public long[] InventorIds { get; set; }
}

public class Inventor
{
    public long Id { get; set; }
    public string Name { get; set; }
}

后续数据是这样创建的:

public static class PatentData
{
    public static readonly Inventor[] Inventors = new Inventor[]
    {
        new Inventor(){
            Name="Benjamin Franklin", Id=1 },
        new Inventor(){
            Name="Orville Wright", Id=2},
        new Inventor(){
            Name="Wilbur Wright", Id=3}
    };
    public static readonly Patent[] Patents = new Patent[]
    {
        new Patent(){
            Title="Bifocals", YearOfPublication="1784",
            InventorIds=new long[] {1}},
        new Patent(){
            Title="Flying machine", YearOfPublication="1903",
            InventorIds=new long[] {2,3}}
    };
}

为了遍历特定专利的所有发明者,我使用下面的代码。

IEnumerable<Patent> patents = PatentData.Patents;
IEnumerable<Inventor> inventors = PatentData.Inventors;

foreach(Patent p in patents)
{
    var iall = inventors.Where(i => p.InventorIds.Contains(i.Id));
    foreach (Inventor i in iall)
    {
        Debug.WriteLine(p.Title + ": " + i.Id);
    }
}

虽然上面的代码运行良好,但我真的很想使用 LINQ Join 语句。显然,问题在于 LINQ Join 语句会抱怨不同的类型(long 和 long[]),它们分别是主键和外键。

我本来希望使用但似乎无法正常工作的代码如下:

Patent [] patents = PatentData.Patents;
Inventor [] inventors = PatentData.Inventors;

var result = patents.Join(inventors, patent => patent.InventorIds, inventor => inventor.Id, (patent, inventor) => new
{
    patent.Title,
    inventor.Name
});

这是失败的,非常正确,出现以下错误:

错误 CS0411:无法从中推断方法“System.Linq.Enumerable.Join(System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable, System.Func, System.Func, System.Func)”的类型参数用法。尝试明确指定类型参数。

所以,我的问题是:

与这两种类型结合使用时,如何修复出现错误的代码以使用 Join 语句;专利和发明人——根本不修改类型?甚至可能吗?

我很感激我可以更改类型以使它们结构更好,但请幽默一下。

4

2 回答 2

4

您需要为每个单独的专利加入:

var query = from patent in patents
            from inventorId in patent.InventorIds
            join inventor in inventors on inventorId equals inventor.Id
            select new { patent.Title, inventor.Name };

当然,如果您可以避免使用Id模型的一部分,而是将专利的发明人直接与Inventor对象联系起来,那会更简单。

于 2012-09-09T12:51:49.980 回答
1

乔恩的答案正是您所需要的。但是,如果您真的想直接使用Join()(and SelectMany(),由第二个from) 方法表示,而不是隐藏在 LINQ 查询语法后面,您也可以这样做。虽然在这种情况下它要复杂得多:

patents.SelectMany(patent => patent.InventorIds,
                   (patent, inventorId) => new { patent, inventorId })
       .Join(inventors, x => x.inventorId, inventor => inventor.Id,
             (x, inventor) => new { x.patent.Title, inventor.Name })
于 2012-09-09T14:19:46.187 回答