我有以下课程:
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; }
}
我知道我可以使用这样的Linq查询:
.Where(a => a.SubjectId == subjectId)
但是我怎么能这样做呢?还有另一个条件
.Where(a => a.ContentTypeId == contentTypId)
有没有一种方法可以将这些加入到哪一个或者它们应该保持为两个?
答案 0 :(得分:6)
仅使用一个包含所有条件的Where
子句:
.Where(a => a.SubjectId == subjectId && a.ContentTypeId == contentTypId)
或两个Where
条款,分别处理一个条件:
.Where(a => a.SubjectId == subjectId)
.Where(a => a.ContentTypeId == contentTypId)
是等效的,因为LINQ查询执行被推迟到调用结果。
答案 1 :(得分:3)
你也可以这样做:
.Where(a => a.SubjectId == subjectId).Where(a => a.ContentTypeId == contentTypId)
这对于在代码中动态构建查询非常有用。
答案 2 :(得分:1)
让我们看一下以下示例:
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);
产生以下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
//链接示例:
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);
//导致以下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
示例显示有呼叫和第二个接收第一个结果作为输入
所以在Linq to Objects
中会有性能受损
性能恶化的程度将取决于数据量和where子句的顺序,第一个子句将过滤得越多,下一个子句将不得不操作等等......
在我看来,在大多数情况下,性能影响不会很大。
在Linq to SQL
链接Where子句对性能没有影响,因为将创建相同的SQL。