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)' の型引数を推論できません使用法。型引数を明示的に指定してみてください。

だから、私の質問は:

エラーのあるコードを修正して、2 つのタイプと組み合わせて使用​​した場合に 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()( SelectMany()2 番目の で表されるfromand ) メソッドを直接使用し、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 に答える