Reputation: 24572
I have the following class:
public partial class Content
{
public int ContentId { get; set; }
public int ContentTypeId { get; set; }
public string Title { get; set; }
public string Text { get; set; }
public int SubjectId { get; set; }
public virtual Subject Subject { get; set; }
}
I understand I can use a Linq query like this:
.Where(a => a.SubjectId == subjectId)
However how can I make it so there is another condition
.Where(a => a.ContentTypeId == contentTypId)
is there a way I can join these into one where or should they remain as two?
Upvotes: 1
Views: 313
Reputation: 16351
Using only one Where
clause containing every condition:
.Where(a => a.SubjectId == subjectId && a.ContentTypeId == contentTypId)
Or two Where
clauses, dealing with one condition each:
.Where(a => a.SubjectId == subjectId)
.Where(a => a.ContentTypeId == contentTypId)
is equivalent, as the LINQ query execution is deferred until the call to the result.
Upvotes: 6
Reputation: 2579
omer schleifer answer got me to bench mark the case and eventually to check the created IL to see if there is a performance hit in chaining clause or not..
lets look at the following example:
var numbers = new List<int>() { 1, 2 ,3,4,5,6,7,8,9,10};
IEnumerable<int> query = numbers.Where(x=> x>2 && x<5);
results in the following IL:
IL_0001: newobj System.Collections.Generic.List<System.Int32>..ctor
IL_0006: stloc.2 // <>g__initLocal0
IL_0007: ldloc.2 // <>g__initLocal0
...
...
...
IL_0059: ldloc.2 // <>g__initLocal0
IL_005A: stloc.0 // numbers
IL_005B: ldloc.0 // numbers
IL_005C: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate2
IL_0061: brtrue.s IL_0076
IL_0063: ldnull
IL_0064: ldftn b__1
IL_006A: newobj System.Func<System.Int32,System.Boolean>..ctor
IL_006F: stsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate2
IL_0074: br.s IL_0076
IL_0076: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate2
IL_007B: call System.Linq.Enumerable.Where
IL_0080: stloc.1 // query
IL_0081: ldloc.1 // query
b__1:
IL_0000: ldarg.0
IL_0001: ldc.i4.2
IL_0002: ble.s IL_000A
IL_0004: ldarg.0
IL_0005: ldc.i4.5
IL_0006: clt
IL_0008: br.s IL_000B
IL_000A: ldc.i4.0
IL_000B: stloc.0 // CS$1$0000
IL_000C: br.s IL_000E
IL_000E: ldloc.0 // CS$1$0000
IL_000F: ret
//the chaining example:
var numbers = new List<int>() { 1, 2 ,3,4,5,6,7,8,9,10};
IEnumerable<int> query = numbers.Where(x=> x>2).Where(x => x<5);
//result in the following IL:
IL_0001: newobj System.Collections.Generic.List<System.Int32>..ctor
IL_0006: stloc.2 // <>g__initLocal0
IL_0007: ldloc.2 // <>g__initLocal0
IL_0008: ldc.i4.1
...
...
...
IL_0058: nop
IL_0059: ldloc.2 // <>g__initLocal0
IL_005A: stloc.0 // numbers
IL_005B: ldloc.0 // numbers
IL_005C: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate3
IL_0061: brtrue.s IL_0076
IL_0063: ldnull
IL_0064: ldftn b__1
IL_006A: newobj System.Func<System.Int32,System.Boolean>..ctor
IL_006F: stsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate3
IL_0074: br.s IL_0076
IL_0076: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate3
IL_007B: call System.Linq.Enumerable.Where <--------first where call
IL_0080: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate4
IL_0085: brtrue.s IL_009A
IL_0087: ldnull
IL_0088: ldftn b__2
IL_008E: newobj System.Func<System.Int32,System.Boolean>..ctor
IL_0093: stsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate4
IL_0098: br.s IL_009A
IL_009A: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate4
IL_009F: call System.Linq.Enumerable.Where <--------second where call
IL_00A4: stloc.1 // query
IL_00A5: ldloc.1 // query
b__1:
IL_0000: ldarg.0
IL_0001: ldc.i4.2
IL_0002: cgt
IL_0004: stloc.0 // CS$1$0000
IL_0005: br.s IL_0007
IL_0007: ldloc.0 // CS$1$0000
IL_0008: ret
b__2:
IL_0000: ldarg.0
IL_0001: ldc.i4.5
IL_0002: clt
IL_0004: stloc.0 // CS$1$0000
IL_0005: br.s IL_0007
IL_0007: ldloc.0 // CS$1$0000
IL_0008: ret
The example Shows that there are to where calls and the second one receives the first one results as an input.
So in Linq to Objects
there will be a performance hit.
the magnitude of the performance deterioration will depend on the amount of data and the order of the where clauses the more the first clause will filter the less the next one will have to operate on and so on...
In my opinion in most cases the performance hit wont be significant.
In Linq to SQL
Chaining Where clause will have no affect on performance because the same SQL will be created.
Upvotes: 1
Reputation: 3935
You can also do:
.Where(a => a.SubjectId == subjectId).Where(a => a.ContentTypeId == contentTypId)
this is useful for building queries dynamically in the code.
Upvotes: 3