-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Contains on generic IList/HashSet/ImmutableHashSet will throw exception #17342
Comments
Our current code indeed work on IList rather than List. |
|
So |
And List implements |
This would be an viable solution? else if (method.DeclaringType.GetInterfaces().Any(t => t == typeof(IList) || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IList<>)))
&& string.Equals(method.Name, nameof(IList.Contains))) I think that checking for either the generic and non-generic The only difference is the
This would make the |
else if (method.DeclaringType.GetInterfaces().Any(t => t == typeof(IList) || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(ICollection<>)))
&& string.Equals(method.Name, nameof(IList.Contains))) |
Would use ICollection<> rather than IList<>. |
@smitpatel the latest code (3.1 preview) still fails when I changed public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList<SqlExpression> arguments)
{
if (method.IsGenericMethod
&& method.GetGenericMethodDefinition().Equals(EnumerableMethods.Contains))
{
return _sqlExpressionFactory.In(arguments[1], arguments[0], false);
}
// early return
if (string.Equals(method.Name, nameof(IList.Contains)) == false)
{
return null;
}
// check if it is or has IList interface
if (typeof(IList).IsAssignableFrom(method.DeclaringType))
{
return _sqlExpressionFactory.In(arguments[0], instance, false);
}
// check if it is ICollection<> interface
if (method.DeclaringType.IsGenericType
&& method.DeclaringType.GetGenericTypeDefinition() == typeof(ICollection<>))
{
return _sqlExpressionFactory.In(arguments[0], instance, false);
}
// check if it has ICollection<> interface
var hasICollectionInterface =
method.DeclaringType.GetInterfaces()
.Where(t => t.IsGenericType)
.Select(t => t.GetGenericTypeDefinition())
.Any(t => t == typeof(ICollection<>));
if (hasICollectionInterface)
{
return _sqlExpressionFactory.In(arguments[0], instance, false);
}
return null;
} |
@roji - Can you look into above? We want to make sure that ContainsTranslator handles all generic collection types. (no need to put a lot of effort for exhaustive search, just the ones mentioned in this thread should be good enough) |
Sure @smitpatel, will do that tomorrow. |
@smitpatel ended up simply implementing what you originally proposed: #17342 (comment). Now any one-argument method names Contains on any type which implements ICollection<> will be matched. Continuing to track via this issue, but tell me if you prefer a new one. |
Describe what is not working as expected.
When using the interface IList instead of List and doing Contains you will get the exception
Steps to reproduce
Further technical details
EF Core version: 3.0.0-preview8.19405.11
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10
IDE: Visual Studio 2019 16.3.0 Preview 2.0
The text was updated successfully, but these errors were encountered: