在LINQ表达式中将整数转换为字符串

4

我正在创建一个SelectList,从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");

然而,我希望selectItem文本的格式为“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 to Entities does not recognize the method 'System.String ToString()' method”的问题。如果我尝试这样做:

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

我收到了 "LINQ to Entities does not recognize the method 'System.String Format(System.String, System.Object, System.Object)' method" 的错误信息。
它似乎不允许我将 Int32 转换为字符串。唯一的选择似乎是创建一个 foreach 方法,遍历 GroupWithCount 对象并创建 SelectListItems 的集合,但这样做太疯狂了。肯定有更好的方法!
2个回答

3

如果框架不允许您在LINQ查询中进行更改,那么您可以在接收到结果集后实现它。在结果集中,您已经拥有“mCount”值,您可以遍历集合并相应地修改group_name的值。例如:

var groups = // your query;

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

2
当你使用Linq To Entities时,你需要注意在什么情况下代码会在(数据库)服务器上执行,在什么情况下代码会在客户端上执行。一个有用的起点(虽然不是全部!)是观察你是否使用了IQueryable(服务器),或者使用了IEnumerable(客户端)。
如果你看一下你拥有的声明groups的var语句,并将光标移到它上面,你会发现编译器已经推断出类型为IQueryable<GroupWithCount>。这意味着当你迭代groups时,代码将在服务器上执行。为了使其工作,代码中的所有内容都需要被Entity Framework翻译成SQL。
Entity Framework很好但并不完美,其中一个它不知道如何将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将所有内容都带回来 - 但在这里使用是可以的。

我猜第二个“Select”是不必要的。它将“GroupWithCount”的集合投影到一个新的集合中,只修改了一个字段。相反,我们可以使用“ForEach”并修改原始集合本身。 - Pawan Mishra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接