【问题标题】:Converting Int to String inside a LINQ expression在 LINQ 表达式中将 Int 转换为 String
【发布时间】:2011-11-17 14:46:27
【问题描述】:

我正在创建一个 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 (members)”,但我似乎不能这样做。如果我尝试

         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 无法识别 'System.String ToString()' 方法”。如果我尝试

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

我收到“LINQ to Entities 无法识别方法 'System.String Format(System.String, System.Object, System.Object)' 方法”。

它只是不允许我将 Int32 转换为字符串。似乎唯一的选择是创建一个遍历 GroupWithCount 对象并创建 SelectListItems 集合的 foreach 方法,但这太疯狂了。肯定有更好的办法!

【问题讨论】:

    标签: c# linq linq-to-entities


    【解决方案1】:

    如果框架不允许您在 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(客户端) .

      如果您查看您拥有的语句,该语句有效,并将光标悬停在声明groupsvar 上,您将看到编译器已推断出类型IQueryable<GroupWithCount>。这意味着当您迭代groups 时,代码将在服务器 上执行。为了使其工作,代码中的所有内容都需要由实体框架翻译成 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 恢复所有内容并不是一个好主意 - 但在这里没关系。

      【讨论】:

      • 我猜第二个“选择”不是必需的。它不必要地将“GroupWithCount”的集合投影到一个修改了一个字段的新集合中。相反,我们可以使用“ForEach”并修改原始集合本身。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-26
      • 1970-01-01
      • 2010-10-17
      • 2022-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-20
      相关资源
      最近更新 更多