I am using predicate builder to write the following code:
IEnumerable<int> ids= new List<int> { 47, 48 };
var predicate = PredicateBuilder.False<Customer>();
predicate = predicate.And(x => x.CreatedAt >= fromDate && x.CreatedAt <= toDate);
foreach (var id in ids)
{
predicate = predicate.Or(x => x.Source.Id == id);
}
var result = Database.Set<Customer>().AsExpandable()
.Where(predicate)
.ToList();
The SQL generated looks like (just the WHERE clause):
WHERE ([Filter6].[SourceId] IN (@p__linq__0,@p__linq__1))
AND ([Filter6].[CreatedAt] >= @p__linq__2)
AND ([Filter6].[CreatedAt] <= @p__linq__3)',
N'@p__linq__0 int,
@p__linq__1 int,
@p__linq__2 datetime2(7),
@p__linq__3 datetime2(7)',
@p__linq__0=48,
@p__linq__1=48,
@p__linq__2='2012-02-07 21:59:55.0437985',
@p__linq__3='2012-02-07 22:04:55.5748288'
It looks like id 48 got assigned twice in the SQL. Not sure why?
You are closing over the loop variable. Make a local copy of your
idvariable instead:Since Linq is lazy your
Orpredicate and henceidwill only be evaluated when you execute the query and at that time the value ofidis the last item in theidscollection. The behavior offoreachin this regard will be changed in C# 5 where this will not be a problem anymore. For more info read “Closing over the loop variable considered harmful”