1

Suppose I want to set FullName property using string.Format like this:

var userList = users.Select(user => new User()
            {
                Id = user.Id,
                UserName = user.UserName,
                FirstName = user.FirstName,
                LastName = user.LastName
                FullName = string.Format("{0} {1}", user.UserName, user.FirstName)
            }).ToList();

This obviously doesn't work because LINQ doesn't know about string.Format.

My question is what are the other options beside going over the list in memory and setting FullName for each item?

userList.ForEach(u => u.FullName = string.Format("{0} {1}", user.UserName, user.FirstName))

UPDATE: to see what I need, please see my conversation with @octavioccl below

Don Box
  • 3,166
  • 3
  • 26
  • 55
  • 2
    http://stackoverflow.com/questions/19147589/linq-to-entities-does-not-recognize-neither-string-format-nor-concatenation – Steve Greene Apr 05 '16 at 16:15
  • 2
    LINQ doesn't have any issues. It's EF that complains, because `String.Format` can't be translated to SQL. You *can't* use any function that can't be translated. Why don't you simply use `+` ? – Panagiotis Kanavos Apr 05 '16 at 16:18
  • thank you, my mind is set to always use `string.Format` instead of `+` operator because in my opinion it makes concatenation more readable. but I guess this is a good exception – Don Box Apr 05 '16 at 16:22

3 Answers3

2

String.Format is not supported in EF, try this way:

FullName = user.UserName + " " + user.FirstName

In this link you will find all CLR methods that are supported

ocuenca
  • 38,548
  • 11
  • 89
  • 102
  • Thank you. Curious, is there a way to make this work using string.Format ? Is it possible to implement it and somehow inject it into EF, such that when EF is creating the results in memory to use it? – Don Box Apr 05 '16 at 16:18
  • Yes, you can do that calling `AsEnumerable` extension method before your `Select`. Calling that method, you are telling that you want to switch from Linq to Entities to Linq to Objects, so what you do next it would be done in memory. But be careful using `AsEnumerable` in all your DbSet, it can affect the performance of your application – ocuenca Apr 05 '16 at 16:22
  • Hmm, but `AsEnumerable` will return data from SQL Server in memory, so the `Select` will enumerate over an already existing collection of objects in memory. It's exactly the scenario I want to avoid, like I said in the question I could just run `userList.ForEach(u => u.FullName = string.Format("{0} {1}", user.UserName, user.FirstName)) `. I was wondering if you can't inject right at the moment EF creates the object in memory – Don Box Apr 05 '16 at 16:25
  • No, as far as I know :(. The problem is the fields you need to use come from your DbSet, if they were, eg, parameters of your query, you could apply the format that you need outside of your query and later use it inside. but not in this case – ocuenca Apr 05 '16 at 16:28
  • It would pretty bad if there is no other way. I think it's very important not to be forced to go over the collection in memory again just to set call some CLR methods which EF can't handle (for a good reason) – Don Box Apr 05 '16 at 16:50
  • @MikeFills You are right - everything will be in memory after call to `AsEnumerable()`. Thus, you should try to narrow down the results before calling it. – Ingweland Apr 05 '16 at 18:01
2

you can use it:

FullName = user.UserName + " " + user.FirstName

But I think that it could be better solution (of cource if it's possible for you):

public class User
{
   public int Id {get;set;}
   public string UserName {get;set;}
   public string FirstName {get;set;}
   public string LastName {get;set;}
   public string FullName
   {
      get
      {
         return string.Format("{0} {1}", FirstName, LastName);
      }
   }
}

then in your query build it:

var userList = users.Select(user => new User()
            {
                Id = user.Id,
                UserName = user.UserName,
                FirstName = user.FirstName,
                LastName = user.LastName
            }).ToList();
Marek Woźniak
  • 1,766
  • 16
  • 34
0

Another object is to project to an anonymous type without that property, then project to the final type in linq-to-objects:

var userList = users.Select(user => new {
                        Id = user.Id,
                        UserName = user.UserName,
                        FirstName = user.FirstName,
                        LastName = user.LastName
                        })
                   .AsEnumerable()
                   .Select(user => new User()
                        {
                        Id = user.Id,
                        UserName = user.UserName,
                        FirstName = user.FirstName,
                        LastName = user.LastName
                        FullName = string.Format("{0} {1}", user.UserName, user.FirstName)
                        })
                    .ToList();
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • thanks but not a good idea. you're duplicating code and iterating over an already created collection in memory – Don Box Apr 06 '16 at 16:13