C# Multiple Generic List‹t› — объединить их?

Сценарий:

У меня есть общий список аудитов и общий список AuditImages. Эти два списка были составлены из таблиц базы данных. В результате ОДИН AuditImage может иметь МНОЖЕСТВО аудитов. Как вы увидите ниже, классы, на которые сопоставляются таблицы, соединяются отношением внешнего ключа «ImageID», когда они находятся в базе данных, однако после извлечения данных в списки в коде «ФИЗИЧЕСКОЕ СОЕДИНЕНИЕ» отсутствует.

Классы, на которые сопоставляются таблицы БД:

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; }
}

Проблема:

Теперь я хочу составить список объектов «Trail», извлекая данные из каждого списка и объединяя их в «Audit.ImageID == AuditImage.ImageID» в новый список.

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; }
}

(Вышеупомянутое по существу объединяет поле «LowResUrl» с каждым аудитом на основе того же ImageID.)

Вопрос:

Как мне это сделать!? Я думал об использовании циклов foreach и linq для создания нового списка объектов тропы, но я не могу придумать, как именно я буду это делать?!

Помощь будет принята с благодарностью.


person Goober    schedule 30.09.2009    source источник
comment
Это пахнет плохим дизайном с самого начала. Почему вы связываете классы с идентификаторами вместо того, чтобы помещать экземпляры AuditImage в свои экземпляры аудита?   -  person cllpse    schedule 30.09.2009
comment
Раздражающий дизайн приложения Silverlight с грязным кодом на стороне сервера .......   -  person Goober    schedule 30.09.2009


Ответы (7)


ты мог бы сделать


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 };
person Mike Two    schedule 30.09.2009

Попробуйте метод расширения Intersect в списке: http://msdn.microsoft.com/en-us/library/bb910215.aspx

Я также думаю, что вам следует пересмотреть свой дизайн и ввести общий интерфейс IAudit или что-то подобное.

person Gerrie Schenck    schedule 30.09.2009
comment
Как должны пересекаться решить эту проблему? - person Stefan Steinegger; 30.09.2009

Это может сработать .......

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();
        }
person Goober    schedule 30.09.2009

Я бы, вероятно, использовал методы расширения, просто потому, что я не очень разбираюсь в 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,
  });
person Stefan Steinegger    schedule 30.09.2009

Это решит проблему.. из запроса 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 }
person Jaswant Agarwal    schedule 30.09.2009
comment
Почему бы не создавать тропы напрямую? - person Stefan Steinegger; 30.09.2009

Зависит от того, чего вы хотите:

Внутреннее соединение (отображать 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 };
person tofi9    schedule 30.09.2009

Есть как минимум два варианта.

Сначала выполните простое соединение:

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 уникален, но лично мне больше нравится подзапрос, потому что он выглядит более естественным, чем соединение.

person Konstantin Spirin    schedule 30.09.2009