How do you implement the equivalent of SQL IN() using .net

In .net (c# or vb) expressions, how would you implement SQL's handy IN() functionality?

i.e. value in (1, 2, 4, 7)

rather than:

value = 1 or value = 2 or value = 4 or value = 7

19
задан Peter C 2 July 2015 в 11:24
поделиться

7 ответов

using System;
using System.Linq;

static class SqlStyleExtensions
{
    public static bool In(this string me, params string[] set)
    {
       return set.Contains(me);
    }
}

Использование:

if (Variable.In("AC", "BC", "EA"))
{

} 
25
ответ дан 30 November 2019 в 02:07
поделиться

Я сделал для этого метод расширения, который считаю весьма полезным. Однако это не более чем синтаксический сахар, оборачивающий существующую функцию IEnumerable.Contains ().

/// <summary>
/// Returns true if the value is represented in the provided enumeration.
/// </summary>
/// <typeparam name="T">Type of the value</typeparam>
/// <param name="obj">The object to check if the enumeration contains</param>
/// <param name="values">The enumeration that might contain the object</param>
/// <returns>True if the object exists in the enumeration</returns>
public static bool In<T>(this T obj, IEnumerable<T> values) {
    return values.Contains(obj);
}

Изменить: Кто-то меня опередил, черт возьми. Я останусь здесь по почте, так как это более общая версия.

13
ответ дан 30 November 2019 в 02:07
поделиться

Я знаю, что здесь МОЖНО найти ответы, но вот мой взгляд на эту тему, который ежедневно используется в SubSonic. это метод расширения:

public static IQueryable<T> WhereIn<T, TValue>(
                this IQueryable<T> query,
                Expression<Func<T, TValue>> selector, 
                params TValue[] collection) where T : class
{
    if (selector == null) throw new ArgumentNullException("selector");
    if (collection == null) throw new ArgumentNullException("collection");
    ParameterExpression p = selector.Parameters.Single();

    if (!collection.Any()) return query;

    IEnumerable<Expression> equals = collection.Select(value =>
       (Expression)Expression.Equal(selector.Body,
            Expression.Constant(value, typeof(TValue))));

    Expression body = equals.Aggregate(Expression.Or);
    return query.Where(Expression.Lambda<Func<T, bool>>(body, p));
}

и WhereNotIn:

public static IQueryable<T> WhereNotIn<T, TValue>(
                this IQueryable<T> query, 
                Expression<Func<T, TValue>> selector, 
                params TValue[] collection) where T : class
{
    if (selector == null) throw new ArgumentNullException("selector");
    if (collection == null) throw new ArgumentNullException("collection");
    ParameterExpression p = selector.Parameters.Single();

    if (!collection.Any()) return query;

    IEnumerable<Expression> equals = collection.Select(value =>
       (Expression)Expression.NotEqual(selector.Body,
            Expression.Constant(value, typeof(TValue))));

    Expression body = equals.Aggregate(Expression.And);

    return query.Where(Expression.Lambda<Func<T, bool>>(body, p));
}

использование:

var args = new [] { 1, 2, 3 };
var bookings = _repository.Find(r => r.id > 0).WhereIn(x => x.BookingTypeID, args);
// OR we could just as easily plug args in as 1,2,3 as it's defined as params
var bookings2 = _repository.Find(r => r.id > 0).WhereIn(x => x.BookingTypeID, 1,2,3,90);

var bookings3 = _repository.Find(r => r.id > 0).WhereNotIn(x => x.BookingTypeID, 20,30,60);

это действительно заставляет меня улыбаться каждый раз, когда я просматриваю его :)

jim

[править] - изначально получен отсюда на SO, но модифицирован для использования iqueryable и параметров: Обходной путь 'Contains ()' с использованием Linq to Entities?

8
ответ дан 30 November 2019 в 02:07
поделиться

Вы можете использовать метод Contains () в списке.

    int myValue = 1;
    List<int> checkValues = new List<int> { 1, 2, 3 };

    if (checkValues.Contains(myValue))
        // Do something 
3
ответ дан 30 November 2019 в 02:07
поделиться

Использование LINQ

var q = from x in collection
        where (new int[] { 1, 2, 4, 7}).Contains(x.value)
        select x
3
ответ дан 30 November 2019 в 02:07
поделиться
if((new int[] {1, 2, 4, 7}).Contains(value))
{
    // Do some work.
}

Как указывали другие, вы можете создать метод расширения In () (я сохраню его общим, чтобы вы могли использовать его с любым типом):

public static bool In<T>(T this obj, IEnumerable<T> col)
{
    return col.Contains(obj);
}

Таким образом, начальный пример становится :

if(value.In(new int[] {1, 2, 4, 7}))
{
    // Do some work.
}
6
ответ дан 30 November 2019 в 02:07
поделиться

Если вы будете выполнять много поисков в одном и том же наборе данных, то с точки зрения производительности лучше использовать HashSet.

HashSet<int> numbers = new HashSet<int> { 1, 2, 4, 7 };
bool is5inSet = numbers.Contains(5);
1
ответ дан 30 November 2019 в 02:07
поделиться