18

In a Linq query, if I'd want to select all properties except for a specific property, what would I do?

I can't use Select() and specify all properties except the one I don't want, because I don't know some of the properties (I query a list of abstract class).

I can't also just select all properties because that'd throw a circular reference was detected while serializing an object of type X. (I'm serializing the object to Json)

Is there any Filter() method or some extension method I can use?

Thanks.

Alon Gubkin
  • 56,458
  • 54
  • 195
  • 288
  • 1
    How about `Select(ALL_STUFF).Except(WHAT_YOU_DONT_WANT)`? – Cipi Jun 25 '11 at 13:10
  • I think the short answer is no; the long answer is, you'll have to be more specific in what you intend to do for a workaround. – Marc Jun 25 '11 at 13:12
  • 8
    @Cipi: `Except` is about rejecting whole elements of the result, not about projecting elements. – Jon Skeet Jun 25 '11 at 13:12
  • 1
    Can someone explain the downvotes? What's wrong with this question? – Alon Gubkin Jun 25 '11 at 13:25
  • 2
    Some people seem to just down-vote things they dislike rather than sticking to the site guidelines - questions that show little research or are badly expressed, answers which show bad-practise or are just plain wrong. I'll upvote it to help :) – BonyT Jun 25 '11 at 14:12
  • Projection wise, the opposite of Select is Select-something-else. Can you give an example of what you have coming in and what you would like to see coming out? – Tormod Jun 25 '11 at 16:06

4 Answers4

23

No, you can't do that - there's nothing like that at all. Bear in mind that you have to end up with a particular type as a result of the projection... if you don't know what properties you're going to select, how can you have such a type?

If you're querying a list of some abstract class, is there any reason you don't want to just keep a reference to the instance of that abstract class? What benefit is there in separating it out into specific properties? Or are you really trying to avoid seeing those properties later on, e.g. for databinding?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Yes, I am trying to avoid some properties, not for databinding, but because some properties create a circular reference. I have edited my question to explain this, so maybe we can find another solution? – Alon Gubkin Jun 25 '11 at 13:17
  • 3
    @Alon: It sounds like you need to change how you serialize rather than the query then. – Jon Skeet Jun 25 '11 at 13:21
  • 1
    Umm, how would I do that? I'm using ASP.NET MVC's `Json()` method to return a `JsonResult` in my view. – Alon Gubkin Jun 25 '11 at 13:23
  • 2
    @Alon: You'd have to see whether there's anything within that call that can do so - but do you see why you *can't* do it at the LINQ level? What type would you expect the result to be, when the properties aren't known until execution time? You could *potentially* do something around this using dynamic typing, but it would be unusual to say the least. – Jon Skeet Jun 25 '11 at 13:50
3

If JSON serialisation is the real problem you are trying to fix then check out the post called JSON and Circular Reference Exception. One recommendation is to use the ScriptIgnoreAttribute Class which "Specifies that JavaScriptSerializer will not serialize the public property or public field". There are also some other clever ways around it in the post worth considering.

Community
  • 1
  • 1
Dan Diplo
  • 25,076
  • 4
  • 67
  • 89
  • 1
    Actually, this is exactly what I was looking for, but since the real answer for the question "what is the opposite of .Select" is Jon Skeet's answer, I will have accept it. Thank you! – Alon Gubkin Jun 25 '11 at 23:33
1

Depending on how many properties you're talking about, your best bet could be just to type out the ones you DO want. As Jon Skeet notes, there's nothing pre-built in LINQ that does what you're describing, because it's a very unusual task.

That being said, if you're dealing with so many properties that it's a huge pain to write -- e.g. something like...

return query.Select(q => new
                   {
                       Prop1 = q.Prop1,
                       Prop2 = q.Prop2,
                       //...
                       Prop3000 = q.Prop3000
                   });

...then there are two options that spring to mind:

  • Use a script to generate the code for you - probably by using reflection to print a list of the class's properties and C&Ping it into your code.
  • Use reflection in your live code, using the PropertyInfo class and filtering by PropertyInfo.Name.

I've done both of these (for other reasons), so I know they work. However, I strongly recommend the first option if you can get it running. Using reflection in the live code will be slower, probably more error-prone, and more difficult to understand when another developer comes along. The only reason I used it was because the class I was working with came from somewhere else, and was subject to frequent changes.

If you do use the first one, might want to keep the code in a separate helper class. Nobody wants a jillion lines of property-selection cluttering up an important method.

Justin Morgan - On strike
  • 30,035
  • 12
  • 80
  • 104
  • Thank you, I have to end up with the first option, sadly the entity contains 150 properties and I only need 149, ohmygod! – Muflix Aug 08 '21 at 08:31
1

Well, what exactly is it you want to achieve? If you want to solve circular issues before serialization, why not traverse the object model then, and set all backreferences to null?

public class MyClass{  
  public List<MyClass> Children {get;set;}  
  public MyClass Parent {get;set;}  

  public void ClearParents(){  
    this.Parent = null;  
    this.Children.ForEach(e => e.ClearParents());  
  }  
}
Johny Skovdal
  • 2,038
  • 1
  • 20
  • 36