Преобразование Int в строку внутри выражения LINQ - PullRequest
4 голосов
/ 17 ноября 2011

Я создаю список 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 был в формате «имя_группы (члены)», но я не могу этого сделать. если я попытаюсь

         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 в строку. Кажется, что единственный вариант - создать метод foreach, который перебирает объекты GroupWithCount и создает коллекцию SelectListItems, но это безумие. Должен быть лучший способ!

Ответы [ 2 ]

3 голосов
/ 17 ноября 2011

Если инфраструктура не позволяет вам вносить изменения в запрос LINQ, вы можете достичь этого после получения набора результатов. В наборе результатов у вас уже есть значение «mCount», вы можете перебрать коллекцию и соответствующим образом изменить значение group_name. Например,

var groups = // your query;

groups.ForEach(item => item.group_name = item.group_name + item.mCount.ToString);
2 голосов
/ 17 ноября 2011

Когда вы работаете с Linq To Entities, вам часто нужно знать границу между тем, что выполняется на сервере (базы данных), и тем, что выполняется на клиенте.Полезной отправной точкой (хотя отнюдь не всей историей!) Для работы с этим является наблюдение, когда вы работаете с IQueryable (сервер) и когда вы работаете с IEnumerable (клиент).

Если вы посмотрите на имеющуюся у вас статистику и наведете курсор на var, который объявляет groups, вы увидите, что компилятор выводит тип 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 - но здесь все в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...