2011-11-17 57 views
4

里面我创建一个的SelectList从LINQ查询填充的下拉列表。这工作:转换诠释为String LINQ表达式

// my temp class for including the member count 
public class GroupWithCount 
{ 
    public string group_name { get; set; } 
    public int group_id { get; set; } 
    public int members { get; set; }   
} 

var groups = from g in DB.Groups 
    where g.user_id == user_id 
    let mC = (from c in DB.Contacts where c.group_id == g.group_id select c).Count() 
     select new GroupWithCount 
     { 
      members = mC, 
      group_id = g.group_id, 
      group_name = g.group_name 
     }; 
model.Groups = new SelectList(groups, "group_id", "group_name"); 

不过,我想选择信息文本是格式“GROUP_NAME(成员)”,但我似乎无法做到这一点。如果我尝试

  select new GroupWithCount 
     { 
      members = mCount, 
      group_id = g.group_id, 
      group_name = g.group_name + mCount 
     }; 

我得到“无法投类型‘System.Int32’输入‘System.Object的’,”如果我尝试

   group_name = g.group_name + mCount.ToString() 

我得到“LINQ到实体不识别方法'System.String ToString()'方法“。如果我尝试

   group_name = string.Format("{0}{1}", g.group_name,mCount) 

我得到 “LINQ到实体无法识别方法 'System.String格式(System.String,System.Object的,System.Object的)' 方法”。

它只是不会让我转换是的Int32成一个字符串。看起来唯一的选择是创建一个遍历GroupWithCount对象并创建一个SelectListItems集合的foreach方法,但这是疯狂的。一定会有更好的办法!

回答

3

如果框架是不是让你做在LINQ查询的变化,就可以实现它,一旦你收到的结果集。在结果集中,您已具有“mCount”值,您可以遍历集合并相应地修改group_name的值。对于例如

var groups = // your query; 

groups.ForEach(item => item.group_name = item.group_name + item.mCount.ToString); 
+0

工作!我知道必须有一个更简单的方法。谢谢! – roryok

2

当你使用LINQ工作的实体,您经常需要知道什么获取的(数据库)服务器上执行,哪些得到客户端上执行之间的边界。一个有用的起点(但绝不是全部的故事!)来工作了这一点,当你与IQueryable(服务器)的工作,当你与IEnumerable(客户端)的工作是观察。

如果你看看你的陈述,工作原理和光标在var的声明groups,你会看到编译器已经推断出IQueryable<GroupWithCount>的类型。这意味着当您迭代groups时,代码将在服务器上执行。为了实现这一点,代码中的所有内容都需要通过Entity Framework转换为SQL。

实体框架是好的,但并不完美,它不知道如何做的事情之一是翻译调用Int32.ToString()到SQL。所以整件事都被拒绝了。

在这种情况下,修复容易。我们需要的所有信息,在每个GroupWithCount,所以我们可以简单地添加一个.AsEnumerable(),迫使查询服务器端的评估,然后投射到形式,我们希望:

var groups = (from g in DB.Groups 
    where g.user_id == user_id 
    let mC=(from c in DB.Contacts where c.group_id == g.group_id select c).Count() 
     select new GroupWithCount 
     { 
      members = mC, 
      group_id = g.group_id, 
      group_name = g.group_name 
     }) 
    .AsEnumerable() // come to the client 
    // next Select is evaluated on the client 
    .Select(gwc => new GroupWithCount 
     { 
      members = gwc.members, 
      group_id = gwc.group_id, 
      group_name = gwc.group_name + gwc.members.ToString() 
     }; 

AsEnumerable后,一切都将是在客户端进行评估,因此可以包含任意C#代码,包括所需的ToString调用。现在检查var将显示编译器已推断出IEnumerable<GroupWithCount>的类型。

通常它会过滤服务器上,我们想做的事情,比如说的情况下,复杂的,所以它不会是一个好主意,用AsEnumerable,使一切恢复 - 但在这里它的罚款。

+0

我想第二个“选择”不是必需的。不必要地将“GroupWithCount”的集合投影到具有修改的字段的新集合中。相反,我们可以使用“ForEach”并修改原始集合本身。 –