1

I would like to generate a select statement similar to a sql select:

public partial class Person{
    public string Name {get;set;}
    public string FirstName{ get;set;}
    public string DisplayName {get;set;}
    public string Town{get;set;}
    public int Age {get;set;}
}

select p.*, (p.NAME + ', ' + p.FirstName) as DisplayName  from Person p

In linq I would do it like this

from p in Person select new 
{
    p.Name, p.FirstName, p.Age, p.Town, // and so on...
    DisplayName = p.NAME + ', ' + p.FirstName
}

Is there a way to do it like in the sql select without listing every property?

Update :

Because I am working with linqToDB here the original class:

[Table("PERSON")]
public class Person{
    [Column("ID"), PrimaryKey, NotNull]
    public int Id { get; set; }
    [Column("NAME")]
    public string Name {get;set;}
    [Column("FIRST_NAME")]
    public string FirstName{ get;set;}

    public string DisplayName {get;set;}
    [Column("TOWN")]
    public string Town{get;set;}
    [Column("AGE")]
    public int Age {get;set;}
}
Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
Franki1986
  • 1,320
  • 1
  • 15
  • 40
  • `select new Test{Item = p, Name = p.NAME + ', ' + p.FirstName` – Drag and Drop Feb 20 '18 at 07:18
  • 1
    I don't think there is any easy or direct way to achieve this. But, instead of creating a anonymous object, you can define a class with a property that exposes the (Name , FirstName) as DisplayName – Thangadurai Feb 20 '18 at 07:20

4 Answers4

1

yes you would take the entire object into your select statement:

from p in Person select new 
{
    person = p,
    DisplayName = p.Name + ", " + p.FirstName
}

Disclaimer: This selects an anonymous object with 1 property Person person and another string DisplayName. It does not initialize the person.DisplayName property.

another possibility could be to give the class Person the proper getter for the property DisplayName:

public string DisplayName
{
    get { return this.Name + ", " + FirstName; }        
}

It will initialize the property with the desired values every time you try to access it's value. And you select statement becomes very simple:

from p in Person select p;

If you are using Linq to SQL then your class can be partial and you could apply here a third strategy: Create another partial class Person and give it a new constructor which accepts a Person as parameter and handle the initialization there:

public partial class Person
{
    public Person(Person p)
    {
        this.Name = p.Name;
        this.FirstName = p.FirstName;
        this.DisplayName = p.Name + ", " + p.FirstName;
        this.Town = p.Town;
        this.Age = p.Age;
    }
}

your select statement would look like this then:

from p in Person select new Person(p);
Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
  • I am working with linqToDB, so sql to linq. The problem with the second solution is that it doesn't access the database for where restrictions. The first solution is not of type Person it is a new anonymous object. – Franki1986 Feb 20 '18 at 07:23
  • @Franki1986 "working with linqToDB, so sql to linq." if that is the case couldl you please post the original class `Person` from your generated code? As far as I know this class should be partial. – Mong Zhu Feb 20 '18 at 07:25
  • @Franki1986 so you are working with a code first approach? did you write the class or is it auto-generated? Does it work when you declare the class as partial? – Mong Zhu Feb 20 '18 at 07:34
  • @Franki1986 but even if you manually select all columns - that still will not work for where restrictions in the same way. I'd say nothing will work for that. – Evk Feb 20 '18 at 07:34
  • 2
    Bsed on my initial question, the way Mong Zhu described with the copy constructor is the best alternative I think! I am using ProtoBuf-Net for a generic copy constructor, so that this should work. Based on my mapping this is another question that aims calculated fields. I have started an issue on that in linqToDB git.https://github.com/linq2db/linq2db/issues/1004 – Franki1986 Feb 20 '18 at 07:47
  • @mark333...333...333 thank you for the edit, but string interpolation presupposed C# 6.0. which might be not the case here, since OP did not use it in the first place – Mong Zhu Feb 20 '18 at 09:23
0

You can change your existing class in this way, so you don't need to manipulate the name explicitly,

public class Person{
 public string Name {get;set;}
 public string FirstName{ get;set;}
 public string DisplayName {
    get{
         return this.Name+","+this.FirstName;
       }

 }
 public string Town{get;set;}
 public int Age {get;set;}
}
Thangadurai
  • 2,573
  • 26
  • 32
  • Thanks for this, but I explained the problm in my comment to Mong Zhu, I need also a database access over linq, and then this won't work for where restrictions. – Franki1986 Feb 20 '18 at 07:26
0

There is no direct way to do this, if you wanted to select all of your properties you have to do it this way or any suggestions will work above:

var result = yourEntity.ToList(); //If it is a list
var result = yourEntity.FirstOrDefault() //If you only want one item

Then access your result and set DisplayName value:

result.DisplayName = $"{result.Name}, {result.FirstName}";

Or you can use Entity Framework and have a mapper to map each of the objects that you have

jbtamares
  • 778
  • 7
  • 26
0

Change your Person class to:

[Table("PERSON")]
public class Person{
    [Column("ID"), PrimaryKey, NotNull]
    public int Id { get; set; }
    [Column("NAME")]
    public string Name {get;set;}
    [Column("FIRST_NAME")]
    public string FirstName{ get;set;}
    public string DisplayName {get;set;}
    [Column("TOWN")]
    public string Town{get;set;}
    [Column("AGE")]
    public int Age {get;set;}

    public static Person Build(Person person, string displayName)
    {
        if (person != null)
        {
            person.DisplayName = displayName;    
        }
        return person;
    }
}

Usage:

from p in Person select Person.Build(p, p.Name + ', ' + p.FirstName);
Luis
  • 436
  • 4
  • 11