private void MapContainsExpression(MethodCallExpression expression) { DbExpression argExpression = GetDbExpressionForExpression(expression.Arguments[0]); DbExpression dbExpression; var collectionObjExp = expression.Object as ParameterExpression; if (collectionObjExp != null) { // collectionObjExp is a parameter expression. This means the content of the collection is // dynamic. DbInExpression only supports a fixed size list of constant values. // So the only way to handle a dynamic collection is for us to create a single Equals expression // with a DbParameterReference. Then when we intercept that parameter, we will see that it's // for a collection and we will modify the SQL to change it from an "=" to an "in". The single // Parameter Reference is set to the first value in the collection and the rest of the values // are inserted into the SQL "in" clause. string paramName = collectionObjExp.Name; Type paramType = PrimitiveTypeForType(collectionObjExp.Type); var param = CreateParameter(paramName, paramType); dbExpression = argExpression.Equal(param); } else { var listExpression = expression.Object as ListInitExpression; if (listExpression == null) { throw new NotSupportedException(string.Format("Unsupported object type used in Contains() - type = {0}", expression.Object.GetType().Name)); } // This is a fixed size list that may contain parameter references or constant values. // This can be handled using either a DbInExpression (if all are constants) or with // a series of OR conditions. // Find all of the constant & parameter expressions. var constantExpressionList = listExpression.Initializers .Select(i => i.Arguments.FirstOrDefault() as ConstantExpression) .Where(c => (c != null) && (c.Value != null)) // null not supported - can only use DbConstant in "In" expression .Select(c => CreateConstantExpression(c.Value)) .ToList(); constantExpressionList.AddRange(listExpression.Initializers .Select(i => i.Arguments.FirstOrDefault() as UnaryExpression) .Where(c => (c != null) && (c.Operand is ConstantExpression)) .Select(c => CreateConstantExpression(((ConstantExpression)c.Operand).Value))); var parameterExpressionList = listExpression.Initializers .Select(i => i.Arguments.FirstOrDefault() as ParameterExpression) .Where(c => c != null) .Select(c => CreateParameter(c.Name, c.Type)) .ToList(); if (constantExpressionList.Count + parameterExpressionList.Count != listExpression.Initializers.Count) { throw new NotSupportedException(string.Format("Unrecognized parameters in Contains list. Null parameters not supported.")); } if (parameterExpressionList.Any()) { // Have parameters so need to build a series of OR conditions so that we can include the // DbParameterReferences. EF will optimize this into an "in" condition but with our // DbParameterReferences preserved (which is not possible with a DbInExpression). // The DbParameterReferences will be intercepted as any other parameter. dbExpression = null; var allExpressions = parameterExpressionList.Cast <DbExpression>().Union(constantExpressionList.Cast <DbExpression>()); foreach (var paramReference in allExpressions) { var equalsExpression = argExpression.Equal(paramReference); if (dbExpression == null) { dbExpression = equalsExpression; } else { dbExpression = dbExpression.Or(equalsExpression); } } } else { // All values are constants so can use DbInExpression dbExpression = argExpression.In(constantExpressionList); } } MapExpressionToDbExpression(expression, dbExpression); }