C# の複数のジェネリック リスト<t> - それらを結合しますか?[重複]
-
19-09-2019 - |
質問
この質問にはすでに答えがあります:
- LINQ で複数のリストを結合できますか? 2 つの答え
シナリオ:
Audit の一般的なリストと AuditImage の一般的なリストがあります。これら 2 つのリストはデータベース テーブルから編集されたものです。この結果、1 つの AuditImage に多数の監査が含まれる可能性があります。以下でわかるように、テーブルがマップされるクラスは、データベース内にあるときは外部キー関係「ImageID」によって結合されますが、データがコード内でリストに抽出されると、「物理結合」は存在しません。
DB テーブルがマップされるクラス:
public class AuditImage
{
public Guid ImageID { get; set; }
public string LowResUrl { get; set; }
}
public class Audit
{
public Guid AuditID { get; set; }
public Guid ImageID { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
public string Comment { get; set; }
}
問題:
ここで、各リストからデータを抽出し、それを「Audit.ImageID == AuditImage.ImageID」で新しいリストに結合することにより、「Trail」オブジェクトのリストをコンパイルしたいと考えています。
public class Trail
{
public Guid ImageID { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
public string Comment { get; set; }
public string LowResUrl { get; set; }
}
(上記は基本的に、同じ ImageID に基づいて「LowResUrl」フィールドと各監査を組み合わせます。)
質問:
これはどうすればいいでしょうか!?foreach ループと linq を使用して証跡オブジェクトの新しいリストを作成することを考えていましたが、具体的にどのようにすればよいのか全く思いつきません。
ご協力をよろしくお願いいたします。
解決
あなたが行うことができます。
var trails = from audit in audits
join image in auditImages on audit.ImageId equals image.ImageId
select new Trail { ImageID = audit.ImageId, CreatedDate = audit.CreatedDate,
CreatedBy = audit.CreatedBy, Comment = audit.Comment,
LowResUrl = image.LowResUrl };
他のヒント
リスト上で交差拡張メソッドを試してみてください。 http://msdn.microsoft .COM / EN-US /ライブラリ/ bb910215.aspxする
私はまた、あなたのデザインを見直し、共通インタフェースIAuditまたは類似した何かを導入すべきだと思います。
これは仕事ができる.......
public List<JobImageAudit> CombineForAuditTrail()
{
var result = from a in auditList
join ai in imageList
on a.ImageID equals ai.ImageID
//into ait // note grouping
select new JobImageAudit
{
JobID = a.JobID,
ImageID = a.ImageID.Value,
CreatedBy = a.CreatedBy,
CreatedDate = a.CreatedDate,
Comment = a.Comment,
LowResUrl = ai.LowResUrl,
};
return result.ToList();
}
私はおそらく、私は非常にLINQに容易ではないんだという理由だけで、拡張メソッドを使用します:
IEnumerable<Trail> trailList = auditImageList.Join(
auditList,
auditImageItem => auditImageItem.ImageId,
auditItem => auditItem.ImageId,
(auditImageItem, auditItem) => new Trail()
{
LowResUrl = auditImageItem.LowResUrl,
ImageID = auditImageItem.ImageId,
CreatedDate = auditItem.CreatedDate,
CreatedBy = auditItem.CreatedBy,
Comment = auditItem.Comment,
});
これは単にループ内のオブジェクトを追うために追加のvarクエリから...問題を解決します。
var query = from auditImage in AuditImageList
join audit in AuditList
on auditImage.ImageID equals audit.ImageID
select new { ImageID= auditImage.ImageID, CreatedDate = audit.CreatedDate, CreatedBy = audit.CreatedBY, Comment = audit.Comment , LowResUrl = auditImage.LowResUrl };
foreach (var trail in query) { //Assign Values to trail object and add to list of trails }
あなたが望むものに依存します:
(それはAuditImage
を持っている場合にのみ表示Audit
を)内部結合ます:
var innerJoin = from image in images
join audit in audits on image.ImageID equals audit.ImageID
select new { image.ImageID, AuditImageId = audit.ImageID };
(それはAuditImage
を持っていない場合でも、表示Audit
を)左が加入ます:
var leftJoin = from image in images
join audit in audits on image.ImageID equals audit.ImageID
into auditCats
from auditCat in auditCats.DefaultIfEmpty(new Audit())
select new { image.ImageID, AuditImageId = auditCat.ImageID };
、少なくとも2つのオプションがあります。
最初はシンプルに参加しますされます:
var trails = Audits.Join(Images, a => a.ImageID, i => i.ImageID, (a, i) =>
new Trail
{
Comment = a.Comment,
CreatedBy = a.CreatedBy,
CreatedDate = a.CreatedDate,
ImageID = a.ImageID,
LowResUrl = i.LowResUrl
});
第二には、サブクエリを使用することです。
var trails = Audits.Select(a =>
new Trail
{
Comment = a.Comment,
CreatedBy = a.CreatedBy,
CreatedDate = a.CreatedDate,
ImageID = a.ImageID,
LowResUrl = Images.Single(i => i.ImageID == a.ImageID).LowResUrl
});
それは参加するよりも自然に見えるのでIMAGEIDはユニークですが、私個人的には、サブクエリ以上のような場合は、の両方が正常に動作する必要があります。