2009-04-02 16 views
13

Bu tartışma için iki tane var, A & B. Bu nesneleri (tabloları) ortak bir ilişki veya yabancı anahtar yoluyla birleştirebilirim. Bu birleştirmeyi yapmak için linq kullanıyorum ve yalnızca ObjectA'yı sonuç kümeme geri döndürmek istiyorum; bununla birlikte, ObejctA'nın bir özelliğini, birleştirme sırasında ObjectB'den gelen verilerle güncellemek istiyorum, böylece LINQ sorgumdan çıkardığım ObjectA'lar, tercih edilen depolama ortamındaki orijinal durumlarından "biraz" farklı. İşte LINQ Satırı Sırasında Satır Mülkiyeti Güncelleştirmesi sırasında Bu

benim sorgu, az önce objectA.SomeProperty gibi bir şey yapabilmek istiyorum görebilirsiniz = objectB.AValueIWantBadly benim seçme yeni yapmak ve yeni OBjectAs yukarı dönmeye biliyorum

ama mümkünse kaçınmak ve sadece bir alanı güncellemek istiyorum.

return from objectA in GetObjectAs() 
    join objectB in GetObjectBs() 
      on objectA.Id equals objectB.AId 
      // update object A with object B data before selecting it 
    select objectA; 

cevap

22

class ClassA { 
    public ClassA UpdateWithB(ClassB objectB) { 
    // Do the update 
    return this; 
    } 
} 

sonra

return from objectA in GetObjectAs() 
    join objectB in GetObjectBs() 
      on objectA.Id equals objectB.AId 
      // update object A with object B data before selecting it 
    select objectA.UpdateWithB(objectB); 

DÜZENLEMEYİ kullanın ClassA bir güncelleme yöntemi ekleyin:

Veya şöyle bir yerel lambda fonksiyonu kullanmak:

Func<ClassA, ClassB, ClassA> f = ((a,b)=> { a.DoSomethingWithB(b); return a;}); 
return from objectA in GetObjectAs() 
     join objectB in GetObjectBs() 
     on objectA.Id equals objectB.AId 
     select f(objectA , objectA); 
+0

bu, '[NotMapped]' özniteliğine sahip bir özelliğe sahip linq-to-sql için çalışmıyor – th1rdey3

0

let ifadesini deneyebilirsiniz? (Değil benim dev makine kendimi bu test etmek): kelimenin itibaren

return from objectA in GetObjectAs() 
join objectB in GetObjectBs() 
on objectA.Id equals objectB.AId 
let objectA.SomeProperty = objectB.AValueIWantBadly 
select objectA; 
+0

hayır, bunu yapamaz; sadece yeni değişkenler yaratır - görev alamaz. –

+0

Bunu denedim, yukarıdaki yorum doğru ... hayır git. – JPrescottSanders

2

"tabloları", bir veritabanından bu verileri alıyorsanız gibi geliyor. Bu durumda; hayır: bunu yapamazsın. Yapmanız olur yapabilirsiniz yakın nesneleri ve ekstra sütunları seçin ve sonrasında özelliklerini güncellemek için: Eğer yaptıklarını ise

var qry = from objectA in GetObjectAs() 
      join objectB in GetObjectBs() 
      on objectA.Id equals objectB.AId 
      select new { A = objectA, 
       objectB.SomeProp, objectB.SomeOtherProp }; 

foreach(var item in qry) { 
    item.A.SomeProp = item.SomeProp; 
    item.A.SomeOtherProp = item.SomeOtherProp; 
    // perhaps "yield return item.A;" here 
} 

LINQ-to-Nesneler, akıcı ile yapabileceğini bazı hacky yolları belki vardır API'ler - hoş değil, yine de. - (düzenleme this other reply gibi)

+0

Bir DB'den veriyorum, ancak bu değişikliklerin DB'ye geri gönderilmesini istemiyorum, yalnızca bu "yeni" nesneyi A'nın bazı farklı verilerle birlikte taşımasına izin verin. – JPrescottSanders

1

İlk önce, LinqExtensions adında bir sınıf oluşturarak her seçeneğe sahip olmak için Linq'i genişletin.

public static class LinqExtensions 
    { 
    public static void Each<T>(this IEnumerable<T> source, Action<T> method) 
    { 
     foreach (var item in source) 
     { 
     method(item); 
     } 
    } 
    } 

Sonra uygun değer ile orijinal nesneler içeren yeni nesnelerin listesini döndürmek için katıl kullanabilirsiniz. Her biri, her bir nesneye değerleri parametre olarak atamanıza veya iletmenize izin vererek bunların üzerine yinelenir.

Atama örneği:

objectA.Join(objectB,a=>a.Id,b=>b.Id,(a,b) => new {a,b.AValueIWant}).Each(o=>o.a.SomeProperty=o.AValueIWant); 

Parametre geçen örnek:

objectA.Join(objectB,a=>a.Id,b=>b.Id,(a,b) => new {a,b.AValueIWant}).Each(o=>o.a.SomeMethod(o.AValueIWant)); 

bu konuda güzel bir şey ObjectA ve ObjectB aynı tip olmak zorunda kalmamasıdır. Bunu bir Sözlük'e (bir arama gibi) eklenen nesnelerin bir listesiyle yaptım. Kötü olan şey, neler olup bittiği belli değil. Her bir uzantıyı atlayıp bunu böyle yazmanız daha iyi olur.

foreach(var change in objectA.Join(objectB,a=>a.Id,b=>b.Id,(a,b) => new {a,b.AValueIWant})) 
{ 
    change.a.SomeProperty = change.AValueIWant; 
    change.a.SomeMethod(change.AValueIWant); 
} 

Ama daha netlik için muhtemelen bu yapacağını:

foreach(var update in objectA.Join(objectB,objectA=>objectA.Id,objectB=>objectB.Id,(objectA,objectB) => new {objectA, Value = objectB.AValueIWant})) 
{ 
    update.objectA.SomeProperty = update.Value; 
} 

o salt okunur olacak ve bu işleri tek nedeni olduğu için, yeni bir nesne bütün ObjectA dönmek gerekecektir Bir koleksiyondaki nesneler, nesnelerdeki özelliklerde değişikliklerinizi yapmanıza olanak tanıyacak şekilde başvurulur. Sonunda, LINQ'ın tümünü bir araya getirmek ve koleksiyonlar arasında dolaşmak ve kibrit arayışında bulunmak, gelecekteki bir bakım için yardımcı olacaktır. LINQ harika ama tıpkı bir çekiçiniz olduğunda herşeyi tırnak yapmıyormuş gibi, bir koleksiyonunuz varsa LINQ cevabı anlamına gelmez.

1

Burada sol birleştirme yapıyorum, böylece objectB'deki karşılık gelen özellik boş olsa bile hala objectA'daki tüm verilere sahibim. Yani, objectB'deki karşılık gelen özellik boşsa, o zaman objectA'da ne yapacağınızı tanımlamanız gerekir. Bu bildirimi, iki veri kümesine katılmak için her zaman kullanırım. ObjectA'daki tüm özellikleri ve bunların nasıl eşlendiğini tam olarak listelemenize gerek yoktur; yalnızca objectB ile güncellemek istediğiniz değerleri listelemeniz gerekir. ObjectA için bir eşleme tanımlanmadığı sürece, objectA'daki önceden var olan değerler güvenlidir.

return from objectA in GetObjectAs() 
    join objectB in GetObjectBs() 
    on objectA.Id equals objectB.AId into combinedObj 
    from subObject in combinedObj.DefaultIfEmpty() 
    // update object A with object B data before selecting it 
    select ((Func<objectAType>)(() => 
    { 
     objectA.property = ((subObject == null) ? "Object B was null" : subObject.property); 
     objectA.property = ((subObject == null) ? "Object B was null" : subObject.property); 
     return objectA; 
    }))() 
0
şunlara deneyebilirsiniz

..

  var list1 = new List<ItemOne> 
         { 
          new ItemOne {IDItem = 1, OneProperty = "1"}, 
          new ItemOne {IDItem = 2, OneProperty = null}, 
          new ItemOne {IDItem = 3, OneProperty = "3"}, 
          new ItemOne {IDItem = 4, OneProperty = "4"} 
         }; 
     var list2 = new List<ItemTwo> 
         { 
          new ItemTwo {IDItem = 2, TwoProperty = "2"}, 
          new ItemTwo {IDItem = 3, TwoProperty = "3"}, 
         }; 


     var query = list1.Join(list2, l1 => l1.IDItem, l2 => l2.IDItem, (l1, l2) => 
     { 
      l1.OneProperty = l2.TwoProperty; 
      return l1; 
     }); 
İlgili konular