2010-08-04 4 views
16

Nelle espressioni .net (C# o vb), come implementeresti la comoda funzionalità IN() di SQL?Come implementare l'equivalente di SQL IN() utilizzando .net

ossia il valore d'(1, 2, 4, 7)

anziché:

value = 1 o value = valore 2 o = 4 o value = 7

+0

quale versione del framework .NET? –

+0

Uso principalmente 3.5. Non sono sicuro se c'è qualcosa in 4.0 che rende più facile questo? –

risposta

21
using System; 
using System.Linq; 

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

Usage :

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

} 
+3

Si può anche impostare la stringa come parametro generico ... I parametri – ngoozeff

+0

rendono la chiamata veramente accurata. –

+3

Versione generica - public static bool In (questo T me, params T [] List) –

4
if((new int[] {1, 2, 4, 7}).Contains(value)) 
{ 
    // Do some work. 
} 

Come altri hanno sottolineato, y ou potrebbe creare un metodo di estensione In() (lo terrò generico in modo da poter utilizzare su qualsiasi tipo):

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

Quindi l'esempio iniziale diventa:

if(value.In(new int[] {1, 2, 4, 7})) 
{ 
    // Do some work. 
} 
+0

Non esiste un metodo 'Array.Contains'. – Conrad

+0

@Conrad - Esiste come parte dei metodi di estensione Enumerable LINQ. http://msdn.microsoft.com/en-us/library/system.linq.enumerable.contains.aspx –

+0

Ahh. Ok, così fa. – Conrad

11

ho fatto un metodo di estensione per questo che trovo abbastanza utile. Tuttavia, non è molto più dello zucchero sintattico che avvolge la funzione IEnumerable.Contains() esistente.

/// <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); 
} 

Edit: Qualcuno mi ha battuto ad esso, dannazione. Qui manterrò per posta visto che è una versione più generica.

+0

wasatz - ho pubblicato una versione di seguito estesa alle funzionalità full expression e lambda. potrebbe essere bello provarlo come alternativa se stai usando qualsiasi IQueryables –

2

È possibile utilizzare il metodo Contains() nell'elenco.

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

    if (checkValues.Contains(myValue)) 
     // Do something 
2

utilizzando LINQ

var q = from x in collection 
     where (new int[] { 1, 2, 4, 7}).Contains(x.value) 
     select x 
1

Se si farà molte ricerche sullo stesso insieme di dati è un bene dal punto di vista delle prestazioni da utilizzare HashSet<T>.

HashSet<int> numbers = new HashSet<int> { 1, 2, 4, 7 }; 
bool is5inSet = numbers.Contains(5); 
8

So che ci sono un sacco di risposte qui, ma qui è il mio prendere in materia, usata quotidianamente in SubSonic. si tratta di un metodo di estensione:

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)); 
} 

e 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)); 
} 

utilizzo:

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); 

questo mi fa davvero sorridere ogni volta ho rivedere it :)

jim

[modifica] - originariamente provenienti da qui su SO, ma modificati per utilizzare params IQueryable e: 'Contains()' workaround using Linq to Entities?

+0

+1 Davvero bello! – wasatz

4

o utilizzando System.Linq ...

(VB.NET)

Enumerable.Contains({1, 2, 4, 7}, value) 

o

{1, 2, 4, 7}.Contains(value) 

(C#)

Enumerable.Contains(new int[]{1, 2, 4, 7}, value); 

o

new int[] {1, 2, 4, 7}.Contains(value); 
+0

Solo questo: '{1, 2, 4, 7}. Contiene (valore)'. – Neolisk

1

Ecco alcune semplici Linq con qualche pseudo codice. Non c'è bisogno di reinventare la ruota.

int[] values = new int[]{1, 2, 4, 7}; 
int target = 2; 
bool contains = values.Any(v => v == target); 

Oppure utilizzare .Contains come alcuni hanno suggerito.

Problemi correlati