2011-02-04 47 views
3

我知道有一種方法可以做到這一點,但我一直在撞牆,試圖找出答案。這工作得很好:選擇與linq的匿名代表

private GenericRecord CreateGeneric(GenericRecord g, Member m) 
{ 
    g.Member = m; 
    return g; 
} 

public IList<GenericRecord> ReportFromDatabase(DateTime startDate, DateTime endDate) 
{ 
    List<GenericRecord> returnRecords = new List<GenericRecord>(); 

    returnRecords.AddRange(from r in pjRepository.Records 
          join m in memberRepository.Members on r.SID equals m.MemberId.ToString() 
          where r.TransactionDate >= startDate && r.TransactionDate <= endDate 
          select CreateGeneric((GenericRecord)r, m)); 

    return returnRecords; 
} 

但我知道有一種方法可以做到這一點沒有CreateGeneric功能。如何選擇內聯委託功能?

returnRecords.AddRange(from r in pjRepository.Records 
         join m in memberRepository.Members on r.SID equals m.MemberId.ToString() 
         where r.TransactionDate >= startDate && r.TransactionDate <= endDate 
         select (delegate 
         { 
          GenericRecord g = (GenericRecord)r; 
          g.Member = m; 
          return g; 
         })); 

這給了我這樣的例外:

The type of the expression in the select clause is incorrect. Type inference failed in the call to 'Select'. 

編輯:另一個失敗的嘗試

returnRecords.AddRange((from r in pjRepository.Records 
         join m in memberRepository.Members on r.SID equals m.MemberId.ToString() 
         where r.TransactionDate >= startDate && r.TransactionDate <= endDate 
         select new { r, m }).Select(x => 
         { 
          GenericRecord g = (GenericRecord)x.r; 
          g.Member = x.m; 
          return g; 
         })); 

這給了我:

lambda表達式與語句b ody不能轉換爲表達式樹。

回答

12

嘗試:

returnRecords.AddRange((from r in pjRepository.Records 
          join m in memberRepository.Members on r.SID equals m.MemberId.ToString() 
          where r.TransactionDate >= startDate && r.TransactionDate <= endDate 
          select new { r, m }).AsEnumerable().Select(x => 
          { 
           GenericRecord g = (GenericRecord)x.r; 
           g.Member = x.m; 
           return g; 
          })); 

關鍵的不同之處在於AsEnumerable()函數。這需要一個IQueryable並返回一個IEnumerable,後者強制Linq提供者對錶達式樹進行評估。這可以防止Linq庫嘗試將第二個Select的lambda轉換爲表達式樹的一部分(它說它不能);第二個Select將改爲對通過評估IQueryable表達式樹生成的實際im-memory集合進行轉換。既然你需要在語句結束之前評估查詢(因此所有元素都可以添加到returnRecords中),那麼應該沒有顯着的性能差異。

+0

太棒了!謝謝! – 2011-02-04 16:57:08

0
Seem like this is what you are looking at: 
class Bila 
    { 
     public string Name; 
     public List<string> Adresses; 
    } 
    var justNumbers = Enumerable.Range(0, 10); 
Func<int,List<string>> foo = delegate(int j) 
    { 
     List<string> lst = new List<string>(); 
     for (int kk = 0; kk < j; kk++) 
     { 
      lst.Add("String_" + kk.ToString()); 
     } 
     return lst; 
    }; 
var zilla3 = (from x in justNumbers 
       select new Bila 
       { 
        Name = "Name_" + x.ToString(), 
        Adresses = foo(x), 
       }).ToArray(); 
+0

提供一些描述。 – Parixit 2014-04-14 08:36:03