C # Multiple common list <t> - Combine them?
Scenario:
I have a generic list of audits and a generic list of AuditImages. These two lists were compiled from database tables. As a result, ONE AuditImage can have many audits. As you will see below, the classes to which the tables are bound are bound by the foreign key relationship "ImageID" when they are in the database, however, once the data is fetched into the lists in the code, there is no "PHYSICAL JOIN".
Classes that appear in DB tables:
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; }
}
Problem:
Now I want to compile a list of "Trail" objects by extracting data from each list and concatenating it in "Audit.ImageID == AuditImage.ImageID" into a new list.
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; }
}
(The above essentially combines the "LowResUrl" field with each audit based on the ImageID, which is the same.)
Question:
How do I do this ?? I was thinking about using foreach and linq loops to create a new list of trail objects, but I can't really think of exactly how I would do this ?!
Help would be greatly appreciated.
source to share
Try the Intersect extension method on List: http://msdn.microsoft.com/en-us/library/bb910215.aspx
I also think you should consider your design and introduce a generic IAudit interface or something similar.
source to share
It might work ........
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();
}
source to share
I would probably use extension methods, just because I'm not very easy on 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,
});
source to share
This will solve the problem .. from the var request just add the trail objects to the loop
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 }
source to share
Depending on what you want:
Inner join (only display AuditImage
if it has Audit
):
var innerJoin = from image in images
join audit in audits on image.ImageID equals audit.ImageID
select new { image.ImageID, AuditImageId = audit.ImageID };
Left join (display AuditImage
even if it doesn't have 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 };
source to share
There are at least two options.
First, a simple join is done:
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
});
Second, you need to use a subquery:
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
});
Both should work fine as long as the ImageID is unique, but I personally like the extra query because it looks more natural than concatenation.
source to share