Проблема с преобразованием int в строку в Linq для сущностей

191
var items = from c in contacts
            select new ListItem
            {
                Value = c.ContactId, //Cannot implicitly convert type 'int' (ContactId) to 'string' (Value).
                Text = c.Name
            };
var items = from c in contacts
            select new ListItem
            {
                Value = c.ContactId.ToString(), //Throws exception: ToString is not supported in linq to entities.
                Text = c.Name
            };

В любом случае я могу это достичь? Обратите внимание, что в VB.NET нет проблем с использованием первого фрагмента, который он отлично работает, VB является гибким, im неспособным привыкнуть к строгости С#!!!

  • 2
    .ToString () также не работает для LinqToEF в VB. ИМХО, вид тупой.
  • 4
    @StingyJack, проблема в ELINQ (сущности linq 2), потому что он переводит ваш код в SQL, а когда дело доходит до внутреннего запроса ToString, он не знает, как преобразовать ToString в SQL. В отличие от объектов linq 2, когда нет перевода, и все является лямбда-выражениями CLR, то это выполняется непосредственно для запрошенных объектов.
Показать ещё 5 комментариев
Теги:
tostring
linq-to-entities

16 ответов

302
Лучший ответ

С EF v4 вы можете использовать SqlFunctions.StringConvert. Нет перегрузки для int, поэтому вам нужно использовать двойную или десятичную. Ваш код будет выглядеть следующим образом:

var items = from c in contacts
            select new ListItem
            {
                Value = SqlFunctions.StringConvert((double)c.ContactId).Trim(),
                Text = c.Name
            };
  • 230
    С какой стати они не включают перегрузку для int?
  • 0
    Это не работает для меня, ошибка меняется на: Указанный метод 'System.String StringConvert (System.Nullable`1 [System.Double])' для типа 'System.Data.Objects.SqlClient.SqlFunctions' не может быть переведен в выражение хранилища LINQ to Entities.
Показать ещё 9 комментариев
11

Я решил аналогичную проблему, поставив преобразование целого в строку из запроса. Это может быть достигнуто путем помещения запроса в объект.

var items = from c in contacts
            select new 
            {
                Value = c.ContactId,
                Text = c.Name
            };
var itemList = new SelectList();
foreach (var item in items)
{
    itemList.Add(new SelectListItem{ Value = item.ContactId, Text = item.Name });
}
6

Использовать LinqToObject: контакты. AsEnumerable()

var items = from c in contacts.AsEnumerable()
            select new ListItem
            {
                Value = c.ContactId.ToString(),
                Text = c.Name
            };
  • 0
    Благодарю. К вашему сведению, я пытаюсь решить немного другую проблему. Я использую LINQ для лиц / лямбда, и это работает. Я пытался преобразовать Int в строку и использовать «Содержит», чтобы найти соответствующие результаты -> т.е. db.contacts.AsEnumerable (). Где (c => c.ContactId.ToString (). Contains ( searchitem )). ToList (); ;
  • 3
    Если вы позвоните в AsEnumerable вы заплатите высокую цену за работу с большими базами данных, потому что это принесет все в память. IEnumerable медленнее по сравнению с IQueryable поскольку последний выполняется исключительно в базе данных.
Показать ещё 1 комментарий
6
public static IEnumerable<SelectListItem> GetCustomerList()
        {
            using (SiteDataContext db = new SiteDataContext())
            {
                var list = from l in db.Customers.AsEnumerable()
                           orderby l.CompanyName
                           select new SelectListItem { Value = l.CustomerID.ToString(), Text = l.CompanyName };

                return list.ToList();
            }
        }
  • 0
    Вы проверяли это, и это работает? прочитайте этот ответ раньше.
  • 0
    Да, я уже использую это. Работает для MVC3, EF4, CTP5, SQL CE4.
Показать ещё 5 комментариев
4
var selectList = db.NewsClasses.ToList<NewsClass>().Select(a => new SelectListItem({
    Text = a.ClassName,
    Value = a.ClassId.ToString()
});

Во-первых, преобразовать в объект, тогда toString() будет правильным.

4

SqlFunctions.StringConvert будет работать, но я нахожу его громоздким, и большую часть времени у меня нет реальной необходимости выполнять преобразование строк на стороне SQL.

Что я делаю, если я хочу выполнять строковые манипуляции, сначала выполните запрос в linq-to-entity, а затем обработайте stings в linq-to-objects. В этом примере я хочу получить набор данных, содержащих Контактное имя и ContactLocationKey, который является конкатенацией строк из двух столбцов Integer (ContactID и LocationID).

// perform the linq-to-entities query, query execution is triggered by ToArray()
var data =
   (from c in Context.Contacts
   select new {
       c.ContactID,
       c.FullName,
       c.LocationID
   }).ToArray();

// at this point, the database has been called and we are working in
// linq-to-objects where ToString() is supported
// Key2 is an extra example that wouldn't work in linq-to-entities
var data2 =
   (from c in data
    select new {
       c.FullName,
       ContactLocationKey = c.ContactID.ToString() + "." + c.LocationID.ToString(),
       Key2 = string.Join(".", c.ContactID.ToString(), c.LocationID.ToString())
    }).ToArray();

Теперь я утверждаю, что громоздко приходится писать два анонимных выделения, но я бы сказал, что это перевешивает удобство, с помощью которого вы можете выполнять строковые (и другие) функции, не поддерживаемые в L2E. Также имейте в виду, что с помощью этого метода возможно ограничение производительности.

2

Брайан Каутхон ответ отличный! Просто небольшое обновление для EF 6, класс переместился в другое пространство имен. Итак, перед EF 6 вы должны включить:

System.Data.Objects.SqlClient

Если вы обновляетесь до EF 6 или просто используете эту версию, включите:

System.Data.Entity.SqlServer

Включив неправильное пространство имен с EF6, код будет компилироваться просто отлично, но вызовет ошибку времени выполнения. Надеюсь, эта заметка поможет избежать некоторой путаницы.

  • 0
    Я должен сказать, что ваш ответ также превосходен. Я обновился до EF6 и всюду искал SqlFunctions. Ваш ответ указал мне в правильном направлении. Я просто добавлю, что вам нужна также ссылка на EntityFramework.SqlServer (у вас может быть только ссылка на EntityFramework).
2

Если ваш "контакт" действует как общий список, я надеюсь, что следующий код будет работать хорошо.

var items = contact.Distinct().OrderBy(c => c.Name)
                              .Select( c => new ListItem
                              {
                                Value = c.ContactId.ToString(),
                                Text = c.Name
                              });

Спасибо.

2

Я столкнулся с этой же проблемой, когда я конвертировал свое приложение MVC 2 в MVC 3 и просто чтобы дать другое (чистое) решение этой проблемы, я хочу опубликовать то, что я сделал...

IEnumerable<SelectListItem> producers = new SelectList(Services.GetProducers(),
    "ID", "Name", model.ProducerID);

GetProducers() просто возвращает коллекцию сущностей производителей. Постскриптум SqlFunctions.StringConvert не работал у меня.

1

Еще одно решение:

c.ContactId + ""

Просто добавьте пустую строку и она будет преобразована в строку.

  • 0
    Возвращенная ошибка: System.NotSupportedException: невозможно преобразовать тип «System.Int64» к типу «System.Object». LINQ to Entities поддерживает только приведение типов примитивов и перечислений EDM.
1

Используя MySql, SqlFunctions.StringConvert не работал у меня. Поскольку я использую SelectListItem в 20+ местах в моем проекте, мне нужно решение, которое работает без искажений 20+ операторов LINQ. Мое решение заключалось в подклассе SelectedListItem, чтобы обеспечить целочисленный сеттер, который перемещает преобразование типов из LINQ. Очевидно, что это решение трудно обобщить, но было весьма полезно для моего конкретного проекта.

Чтобы использовать, создайте следующий тип и используйте в своем запросе LINQ вместо SelectedListItem и используйте IntValue вместо значения.

public class BtoSelectedListItem : SelectListItem
{
    public int IntValue
    {
        get { return string.IsNullOrEmpty(Value) ? 0 : int.Parse(Value); }
        set { Value = value.ToString(); }
    }
}
0

если вы используете инфраструктуру сущности и хотите сделать единственное int приемлемым, тогда вы можете использовать это в запросе linq, вы можете попробовать это

var items = from c in contacts
        select new ListItem
        {
            Value = (int)ContractId 
            Text = c.Name
        };

он будет работать, потому что использование (int) приведет ваше значение к int, поэтому вам не нужно преобразовать строку в int, и вы получите нужный результат.

это сработало для меня в моем проекте, я думаю, это было бы полезно для вас

  • 0
    я отредактировал ответ @Toby Speight, пожалуйста, проверьте ответ сейчас ..
-1

Самый простой способ:

var items = from c in contacts
            select new ListItem
            {
                Value = c.ContactId + "",
                Text = c.Name
            };
-2
var items = from c in contacts
select new ListItem
{
    Value = String.Concat(c.ContactId), //This Works in Linq to Entity!
    Text = c.Name
};

Я обнаружил, что SqlFunctions.StringConvert((double)c.Age) не работает для меня, либо поле имеет тип Nullable<Int32>

В течение последних нескольких дней проб и ошибок я много искал, чтобы найти это.

Я надеюсь, что это поможет нескольким кодировщикам.

  • 1
    Не работает для меня System.String Concat(System.Object) исключение « ... System.String Concat(System.Object) не может быть преобразован в выражение хранилища ... ».
  • 1
    У меня тоже не работает. Я также получаю «System.NotSupportedException: LINQ to Entities не распознает метод метода System.String Concat (System.Object)», и этот метод нельзя преобразовать в выражение хранилища ».
Показать ещё 1 комментарий
-3

Я понимаю, что вам нужно создать частичный класс, чтобы "расширить" вашу модель и добавить свойство, которое доступно только для чтения, которое может использовать остальные свойства класса.

public partial class Contact{

   public string ContactIdString
   {
      get{ 
            return this.ContactId.ToString();
      }
   } 
}

Тогда

var items = from c in contacts
select new ListItem
{
    Value = c.ContactIdString, 
    Text = c.Name
};
  • 0
    Нет, вы не можете использовать пользовательские свойства в LINQ to Entities (в .NET 3.5).
  • 1
    Я не проверял, но это тоже не сработает. так как это не свойство поля таблицы. Я мог бы сначала сделать это с помощью ToArray (), а затем привязать объекты, но я хочу сделать запрос к БД. Я полагаю, не сможет сделать это. Я создал свой собственный ListItem, который принимает поле int. Это работает лучше для меня.
-6

Можете ли вы попробовать:

var items = from c in contacts
        select new ListItem
        {
            Value = Convert.ToString(c.ContactId), 
            Text = c.Name
        };
  • 2
    Нету. не работает
  • 0
    Приведенный выше код не будет работать, так как он выдаст ошибку, в которой говорится, что «LINQ to Entities не распознает метод метода System.String ToString (Int32)», и этот метод нельзя преобразовать в выражение хранилища ».

Ещё вопросы

Сообщество Overcoder
Наверх
Меню