web-dev-qa-db-fra.com

LINQ to Objects Joindre deux collections pour définir des valeurs dans la première collection

J'ai la requête Entity Framework suivante:

var results = from r in db.Results
              select r;

J'utilise AutoMapper pour mapper vers un autre type:

var mapped = Mapper.Map<IEnumerable<Database.Result>, IEnumerable<Objects.Result>>(results);

Dans mon type Objects.Result, j'ai une propriété appelée raison qui ne provient pas de la base de données. Cela provient d'une autre source que je dois repeupler dans mon type mappé:

var reasons = new List<Reason>
{
    new Reason { Id = 1, Reason = "asdf..." }
};

Je dois joindre les motifs à ma collection mappée et définir la propriété Reason dans ma collection mappée à l'aide de la valeur de ma collection de motifs. Est-ce possible?

 // need something like this:
 mapped = from m in mapped
          join r in reasons on m.Id equals r.Id
          update m.Reason = r.Reason
          select m;

Évidemment, le code ci-dessus ne compile pas, mais y a-t-il un code que je peux écrire qui fait ce que je veux?

20
Dismissile

Faites la mutation en boucle. De manière optimale, Linq devrait être exempt de mutations dans la ou les collections contre lesquelles il opère. Utilisez Linq pour filtrer, ordonner, projeter vos données, utilisez les techniques traditionnelles pour modifier.

var joinedData = from m in mapped 
                 join r in reasons on m.Id equals r.Id 
                 select new { m, r };

foreach (var item in joinedData)
{
    item.m.Reason = item.r.Reason;
}
24
Anthony Pegram

Cela pourrait vous faire économiser beaucoup de temps. Le code ci-dessous est pour Joindre deux collections et définir la valeur de propriété de la première collection.

class SourceType
{
    public int Id;
    public string Name;
    public int Age { get; set; }
    // other properties
}

class DestinationType
{
    public int Id;
    public string Name;
    public int Age { get; set; }
    // other properties
}
    List<SourceType> sourceList = new List<SourceType>();
    sourceList.Add(new SourceType { Id = 1, Name = "1111", Age = 35});
    sourceList.Add(new SourceType { Id = 2, Name = "2222", Age = 26});
    sourceList.Add(new SourceType { Id = 3, Name = "3333", Age = 43});
    sourceList.Add(new SourceType { Id = 5, Name = "5555", Age = 37});

    List<DestinationType> destinationList = new List<DestinationType>();
    destinationList.Add(new DestinationType { Id = 1, Name = null });
    destinationList.Add(new DestinationType { Id = 2, Name = null });
    destinationList.Add(new DestinationType { Id = 3, Name = null });
    destinationList.Add(new DestinationType { Id = 4, Name = null });


    var mapped= destinationList.Join(sourceList, d => d.Id, s => s.Id, (d, s) =>
    {
        d.Name = s.Name;
        d.Age = s.Age;
        return d;
    }).ToList();
8

Une méthode de force brute serait: -

foreach(var m in mapped)
{
    m.Reason = reasons.Single(r=> r.Id == m.Id).Reason;
}

En fait, cette implémentation est assez proche de votre pseudo-code.

0
Adam Ralph