2

Error Description: LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression.

The error comes up while executing following code:

public ActionResult NewBooking()
    {
        var db = new VirtualTicketsDBEntities2();

        IEnumerable<SelectListItem> items = db.Attractions
          .Select(c => new SelectListItem
          {
              Value = c.A_ID.ToString(),
              Text = c.Name
          });
        ViewBag.CategoryID = items;
        return View();
    }

Any suggestion to get rid of this error?

Thanks.

Azeem
  • 2,904
  • 18
  • 54
  • 89
  • See [this](http://stackoverflow.com/questions/5899683/linq-to-entities-does-not-recognize-the-method-system-string-tostring-method?rq=1) – jamesSampica Jul 15 '13 at 17:48
  • possible duplicate of [LINQ to Entities does not recognize the method 'System.String ToString()' method](http://stackoverflow.com/questions/4121863/linq-to-entities-does-not-recognize-the-method-system-string-tostring-method) – yoozer8 Jul 15 '13 at 17:49

2 Answers2

9

You can use an AsEnumerable() to change the binding context from Linq-to-Entities to Linq-to-Objects:

IEnumerable<SelectListItem> items = db.Attractions
    .AsEnumerable()
    .Select(c => new SelectListItem
    {
        Value = c.A_ID.ToString(),
        Text = c.Name
    });
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • It worked. Thanks. I will mark your answer correct in 9 minutes. – Azeem Jul 15 '13 at 17:50
  • 6
    Just use `AsEnumerable()` ... `ToList()` is a costly step depending on how much items there are. – Simon Belanger Jul 15 '13 at 17:50
  • This looks really inefficient. If table Attractions is large, we fill a big list of tuples then execute our query. – jamesSampica Jul 15 '13 at 17:51
  • @SimonBelanger There's no filter in the example, so it's not puling any more records than the original code. – D Stanley Jul 15 '13 at 17:51
  • @DStanley I agree, but ToList() effectively builds up the list. You will create an intermediate `List` to then project to the `SelectListItem`. `AsEnumerable()` will only iterate the `Attraction`s, not creating a list. – Simon Belanger Jul 15 '13 at 17:53
  • @SimonBelanger So what's your alternative? You _could_ project to an anonymous type, then to `SelectListItem`, but that seems unnecessary unless `Attraction` is a very heavy class. – D Stanley Jul 15 '13 at 17:56
  • 1
    @DStanley Why project to an anonymous type at all? `db.Attractions.AsEnumerable` will be strongly typed to `Attraction` and then you project to your `SelectListItem`, there's no need for an anonymous object as intermediate. The only different is `ToList` is building the list. The query will still be serialized as `Attraction` then to `SelectList` without the cost of creating a `List`. – Simon Belanger Jul 15 '13 at 18:00
  • @SimonBelanger I'm with you now - I was thinking you were objecting to hydrating `Attraction` ojects - now I see that the additional overhead of copying to a new list is the issue. – D Stanley Jul 15 '13 at 19:54
4

If you want to do the conversion on the database, you need to use an SqlFunction:

public ActionResult NewBooking()
{
    var db = new VirtualTicketsDBEntities2();

    IEnumerable<SelectListItem> items = db.Attractions
      .Select(c => new SelectListItem
      {
          Value = SqlFunctions.StringConvert((double)c.A_ID)
          Text = c.Name
      });
    ViewBag.CategoryID = items;
    return View();
}

The problem is the SqlFunctions are not standard and might not work on all database providers. If that's a problem, use AsEnumerable to leave the Entity Framework's queryable world:

public ActionResult NewBooking()
{
    var db = new VirtualTicketsDBEntities2();

    IEnumerable<SelectListItem> items = db.Attractions.AsEnumerable()
      .Select(c => new SelectListItem
      {
          Value = c.A_ID.ToString()
          Text = c.Name
      });
    ViewBag.CategoryID = items;
    return View();
}
Simon Belanger
  • 14,752
  • 3
  • 41
  • 35