211
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
            };

Is there anyway I can achieve this? Note, that in VB.NET there is no problem use the first snippet it works just great, VB is flexible, im unable to get used to C#'s strictness!!!

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
  • 2
    .ToString() doesn't work for LinqToEF in VB either. IMHO, Kind of stupid. – StingyJack Jul 20 '10 at 18:18
  • 5
    @StingyJack, the problem is with the ELINQ (linq 2 entities), because it translates your code to SQL, and when it comes to an inner ToString request, it doesn't know how to translate 'ToString' to SQL. Unlike with linq 2 objects, when there is no translation, and everything is CLR lambdas, then it's performed directly on the requested objects. – Shimmy Weitzhandler Jul 26 '10 at 22:21
  • 1
    I'm just irritated that they allow that kind of error to be compiled, and that I had to troll forever to find a plain English description of the cause (sans legal-ese and academia-ese). – StingyJack Jul 27 '10 at 20:52
  • 1
    You're right, but they're also right, they're not supposed to translate all the CLR and customized CLR functionality into SQL, especially not in the very early version of EF :) About the ToString, read Brian's answer: http://stackoverflow.com/questions/1066760/problem-with-converting-int-to-string-in-linq-to-entities/3292773#3292773 – Shimmy Weitzhandler Jul 27 '10 at 22:29
  • Great, but how about people using 3.5, no 4? Then what? – Ekaterina Jul 27 '11 at 13:44
  • It seems that the obvious question which nobody has asked is why on earth is the ListItem.Value (property) a string and not an int? – Paul Zahra Apr 01 '16 at 11:58
  • Beacuse that's not the question that was asked. – shawty Jul 18 '17 at 18:57

15 Answers15

321

With EF v4 you can use SqlFunctions.StringConvert. There is no overload for int so you need to cast to a double or a decimal. Your code ends up looking like this:

var items = from c in contacts
            select new ListItem
            {
                Value = SqlFunctions.StringConvert((double)c.ContactId).Trim(),
                Text = c.Name
            };
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Brian Cauthon
  • 5,524
  • 2
  • 24
  • 26
  • 239
    Why on earth wouldn't they include an overload for int? – Jeremy Coenen Oct 01 '10 at 16:59
  • It doesn't work for me, error changes to: The specified method 'System.String StringConvert(System.Nullable`1[System.Double])' on the type 'System.Data.Objects.SqlClient.SqlFunctions' cannot be translated into a LINQ to Entities store expression. – Nestor Apr 24 '11 at 14:35
  • 1
    What does the `SqlFunctions.StringConvert` part of your query look like? From the error it sounds like you are passing a `Nullable` (`double?`) instead of a `double`. Try calling `GetValueOrDefault()` before you pass it in. – Brian Cauthon Apr 25 '11 at 13:23
  • 7
    @Nestor This doesn't work for SQL Compact. Found that out the hard way. – Austin Nov 08 '11 at 21:04
  • An alternative to SqlFunctions.StringConvert is to do the string conversion in linq-to-objects query after you've done your linq-to-entities query; sort of a "post-processing" of your data. It's only one database call, L2O is done in memory. See my answer below for more details. – Walter Stabosz Jan 05 '12 at 14:37
  • 25
    To avoid the whitespaces before the result, you should use `SqlFunctions.StringConvert((double)c.ContactId).Trim()` – Kim Tranjan Mar 15 '12 at 03:47
  • 2
    Seems not to work for SQLite using System.Data.SQLite The Methode 'System.String StringConvert(System.Nullable`1[System.Double])' in Typw 'System.Data.Objects.SqlClient.SqlFunctions' kann nicht in einen Speicherausdruck für 'LINQ to Entities' übersetzt werden. (cannot be translated into "LINQ to Entities") – OneWorld Jan 09 '13 at 10:28
  • 1
    This didn't work for me using regular SQL, the comparison between 1 and "1" was false. – NibblyPig Aug 27 '13 at 15:46
  • @OneWorld they moved the namespace in later version – johnny 5 Nov 21 '16 at 21:01
  • 6
    Excellent answer! Just please note, starting on you are using EF 6, the class got moved to another namespace. So, before EF 6, you should include: "System.Data.Objects.SqlClient" If you update to EF 6, or simply are using this version, include: "System.Data.Entity.SqlServer" By including the incorrect namespace with EF6, the code will compile just fine but will throw a runtime error. I hope this note helps to avoid some confusion. – Leo Dec 22 '16 at 15:27
  • Why that is return ********** ?! – QMaster Aug 11 '18 at 07:12
12

I solved a similar problem by placing the conversion of the integer to string out of the query. This can be achieved by putting the query into an object.

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 });
}
Jente Rosseel
  • 1,195
  • 1
  • 10
  • 18
  • This is one way to solve it, but keep in mind that this will increase time of execution, if u have large amount of objects, this foreach is overkill... – Serlok Jul 12 '19 at 10:26
8

Use LinqToObject : contacts.AsEnumerable()

var items = from c in contacts.AsEnumerable()
            select new ListItem
            {
                Value = c.ContactId.ToString(),
                Text = c.Name
            };
Mohammadreza
  • 3,139
  • 8
  • 35
  • 56
  • Thanks. FYI, I'm trying to solve a slightly different problem. I'm using LINQ to entities / lambda and this works. I was trying to convert an Int to String and use "Contains" to find matching results --> ie db.contacts.AsEnumerable().Where(c => c.ContactId.ToString().Contains(_searchitem_)).ToList(); ; – ejhost Dec 05 '14 at 18:49
  • 11
    If you call `AsEnumerable` you will pay a high performance price on larger databases because it will bring everything in memory. `IEnumerable` is slower in comparison with `IQueryable` because the later is executed exclusively in the database. – CodeArtist Jun 26 '15 at 19:40
5

SqlFunctions.StringConvert will work, but I find it cumbersome, and most of the time, I don't have a real need to perform the string conversion on the SQL side.

What I do if I want to do string manipulations is perform the query in linq-to-entities first, then manipulate the stings in linq-to-objects. In this example, I want to obtain a set of data containing a Contact's fullname, and ContactLocationKey, which is the string concatination of two Integer columns (ContactID and 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();

Now, I grant that it does get cumbersome to have to write two anonymous selects, but I would argue that is outweighed by the convenience of which you can perform string (and other) functions not supported in L2E. Also keep in mind that there is probably a performance penalty using this method.

Walter Stabosz
  • 7,447
  • 5
  • 43
  • 75
4

Brian Cauthon's answer is excellent! Just a little update, for EF 6, the class got moved to another namespace. So, before EF 6, you should include:

System.Data.Objects.SqlClient

If you update to EF 6, or simply are using this version, include:

System.Data.Entity.SqlServer

By including the incorrect namespace with EF6, the code will compile just fine but will throw a runtime error. I hope this note helps to avoid some confusion.

Leo
  • 409
  • 6
  • 7
  • I have to say that _your_ answer is excellent as well. I upgraded to EF6 and have been looking everywhere for SqlFunctions. Your answer pointed me in the right direction. I'll just add that you need a reference to EntityFramework.SqlServer as well (you may only have a reference to EntityFramework). – Metalogic Apr 17 '17 at 18:12
4
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();
            }
        }
Nestor
  • 1,969
  • 4
  • 25
  • 30
  • Did you test it and it works? read [this](http://stackoverflow.com/questions/1066760/problem-with-converting-int-to-string-in-linq-to-entities/1066781#1066781) answer before. – Shimmy Weitzhandler Apr 30 '11 at 21:48
  • Yes, I'm using it already. It works for MVC3, EF4, CTP5, SQL CE4. – Nestor May 01 '11 at 11:50
  • This seems more elegant than boxing to double and using the StringConvert. – CmdrTallen Jul 23 '11 at 14:21
  • I prefer this instead of the accepted answer's suggestion. I worry about the performance impact though. – Peter Aug 14 '11 at 19:27
  • 9
    But in this case you'll fetch all data from database then suppose that you wanna make some filtering on this list before `return list.ToList();` !! – Wahid Bitar Sep 26 '11 at 21:48
  • Yes. Previous solutions here have same issue. In my case this is used only to get a list of type SelectListItem which is to be used for the Combobobx html controls, so no need further filtering. – Nestor Sep 27 '11 at 08:20
  • 4
    When you can't access SqlFunctions you don't have many other options than this. However, I would have used this for my query: `return (from l in db.Customers orderby l.CompanyName select new {Id=l.CustomerID, Name=l.CompanyName}).AsEnumerable().Select(c=> new SelectListItem{Value=c.Id.ToString(), Text = c.Name}).ToList();`. Doing it this way only gets the id/name from the db (instead of all customer properties) and does the sort using the more efficient index on the db. – Brian Cauthon Sep 27 '11 at 19:05
3
var selectList = db.NewsClasses.ToList<NewsClass>().Select(a => new SelectListItem({
    Text = a.ClassName,
    Value = a.ClassId.ToString()
});

Firstly, convert to object, then toString() will be correct.

Kijewski
  • 25,517
  • 12
  • 101
  • 143
phil hong
  • 59
  • 6
3

One more solution:

c.ContactId + ""

Just add empty string and it will be converted to string.

Igor Valikovsky
  • 586
  • 5
  • 5
  • Returned Error: System.NotSupportedException: Unable to cast the type 'System.Int64' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types. – QMaster Aug 11 '18 at 07:20
2

If your "contact" is acting as generic list, I hope the following code works well.

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

Thanks.

Nawaz
  • 124
  • 4
2

I ran into this same problem when I was converting my MVC 2 app to MVC 3 and just to give another (clean) solution to this problem I want to post what I did...

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

GetProducers() simply returns an entity collection of Producers. P.S. The SqlFunctions.StringConvert didn't work for me.

BarryC
  • 21
  • 1
1

Using MySql, the SqlFunctions.StringConvert didn't work for me. Since I use SelectListItem in 20+ places in my project, I wanted a solution that work without contorting the 20+ LINQ statements. My solution was to sub-class SelectedListItem in order to provide an integer setter, which moves type conversion away from LINQ. Obviously, this solution is difficult to generalize, but was quite helpful for my specific project.

To use, create the following type and use in your LINQ query in place of SelectedListItem and use IntValue in place of Value.

public class BtoSelectedListItem : SelectListItem
{
    public int IntValue
    {
        get { return string.IsNullOrEmpty(Value) ? 0 : int.Parse(Value); }
        set { Value = value.ToString(); }
    }
}
raider33
  • 1,633
  • 1
  • 19
  • 21
1

if you use entity framework and you want to make the only int acceptable then you can use this in linq query you can try this

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

it will work because using (int) will cast your value to the int so you don't need any conversion for string to int and you get the result you want.

this worked for me in my project i think it would be helpful for you

Saurabh Solanki
  • 2,146
  • 18
  • 31
-2

My understanding is that you have to create a partial class to "extend" your model and add a property that is readonly that can utilize the rest of the class's properties.

public partial class Contact{

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

Then

var items = from c in contacts
select new ListItem
{
    Value = c.ContactIdString, 
    Text = c.Name
};
Mcbeev
  • 1,519
  • 9
  • 9
  • No, you can't use custom properties in LINQ to Entities (in .NET 3.5). – Craig Stuntz Jul 01 '09 at 12:33
  • 1
    I didn't tested it, but it won't work either. since it's not a table field property. I could first do it with ToArray() then linqing over objects but I want to query the DB. I assume will not be able to do it. I created my own ListItem that takes an int field. That works better for me. – Shimmy Weitzhandler Jul 01 '09 at 13:06
-2
var items = from c in contacts
select new ListItem
{
    Value = String.Concat(c.ContactId), //This Works in Linq to Entity!
    Text = c.Name
};

I found that SqlFunctions.StringConvert((double)c.Age) did not work for me either the field is of type Nullable<Int32>

Took me a lot of searching over the last few days of trial and error to find this.

I hope this helps a few coders out there.

EdChum
  • 376,765
  • 198
  • 813
  • 562
  • 1
    Does not work for me. It throws the exception "*...`System.String Concat(System.Object)` cannot be translated into a store expression...*". – Slauma Mar 05 '13 at 19:26
  • 1
    Doesn't work for me either. I also get "System.NotSupportedException: LINQ to Entities does not recognize the method 'System.String Concat(System.Object)' method, and this method cannot be translated into a store expression." – camainc Sep 03 '13 at 19:07
  • 1
    DOES NOT WORK - DEVOTE THIS ANSWER [NotSupportedException: LINQ to Entities does not recognize the method 'System.String Concat(System.Object)' method, and this method cannot be translated into a store expression.] – Philipp Munin Oct 25 '13 at 17:02
-6

Can you try:

var items = from c in contacts
        select new ListItem
        {
            Value = Convert.ToString(c.ContactId), 
            Text = c.Name
        };
Tony Heupel
  • 1,053
  • 8
  • 11
  • The above code will not work as it will throw an error saying "LINQ to Entities does not recognize the method 'System.String ToString(Int32)' method, and this method cannot be translated into a store expression." – G K Jun 18 '14 at 06:05