2011-02-04 52 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