Soru LINQ'da LIKE operatörü


SQL'lere benzer bir C # LINQ ifadesinde dizeleri karşılaştırmanın herhangi bir yolu var mı LIKE Şebeke?

Bir dize listesi olduğunu varsayalım. Bu listede bir dize aramak istiyorum. SQL'de yazabilirim:

SELECT * FROM DischargePort WHERE PortName LIKE '%BALTIMORE%'

Yukarıdakilerin yerine, sorgu bir linux sözdizimi ister.

using System.Text.RegularExpressions;
…

var regex = new Regex(sDischargePort, RegexOptions.IgnoreCase);
var sPortCode = Database.DischargePorts
                .Where(p => regex.IsMatch(p.PortName))
                .Single().PortCode;

Yukarıdaki LINQ sözdizimi çalışmıyor. Neyin var yanlış?


76
2018-03-21 06:26


Menşei


Bu sorgu aslında sizin yerine koyduğunuzda benim için çalıştı. Ancak, MongoDb Linq sürücüsünü kullanıyorum ve her Linq sağlayıcısında uygulama farklılıkları var ... neyse, teşekkürler. - Mark Ewer


Cevaplar:


Genellikle kullanırsın String.StartsWith/EndsWith/Contains. Örneğin:

var portCode = Database.DischargePorts
                       .Where(p => p.PortName.Contains("BALTIMORE"))
                       .Single()
                       .PortCode;

LINQ ile SQL üzerinden düzgün düzenli ifadeler yapmanın bir yolu var mı bilmiyorum. (Kullandığınız sağlayıcıya gerçekten bağlı olduğunu unutmayın - LINQ'dan Objects'e kadar iyi olurdu; bu, sağlayıcının aramayı kendi yerel sorgu biçimine, örn. SQL'e dönüştürebilmesi meselesidir.)

EDIT: BitKFu'nun dediği gibi, Single beklediğinizde kullanılmalıdır tam olarak bir sonuç - durumun böyle olmaması için bir hata olduğunda. Seçenekleri SingleOrDefault, FirstOrDefault veya First bağlı olarak kullanılmalıdır kesinlikle Beklenenler.


120
2018-03-21 06:28



arkadaşım, ama bir sorun var, Listem "BALTIMORE" içeriyor ve verilen karşılaştırma parametresi "BALTIMORE [MD], ABD" .Adı sözdizimi seçilemiyor. - shamim
Aşağıdaki ifademe bir göz atın, Single () yönteminden gelebilir. FirstOrDefault () kullanmak daha iyidir - BitKFu
@shamim: Yani verileriniz aradığınız dizeyi içermiyor mu? SQL'de bile çalışmasını nasıl beklersiniz? - Jon Skeet
SQL'de sonuç kümesine sahip olamazsınız - C # içinde bir istisna alırsınız. Hangi sonuç yerine biraz farklıdır. Bu yüzden FirstOrDefault'u kullanmamı önerdim. - BitKFu
@BitKFu bir başlangıç ​​noktasından Single(), SingleOrDefault() Tam bağlamı anlamadıkça bir sonraki adım olurdum ... - Marc Gravell♦


Regex? yok hayır. Fakat bu sorgu için sadece kullanabilirsiniz:

 string filter = "BALTIMORE";
 (blah) .Where(row => row.PortName.Contains(filter)) (blah)

Eğer sen Gerçekten mi SQL istiyorum LIKE, kullanabilirsiniz System.Data.Linq.SqlClient.SqlMethods.Like(...)LINQ-to-SQL için eşler LIKE SQL Server'da.


28
2018-03-21 06:29



EF4'te ne var? - Maslow
@Maslow - uzmanlık alanım değil, korkarım - ama tüm EF uygulamalarına göre güzel bir temiz yol olduğunu düşünmüyorum, yani ... hayır. - Marc Gravell♦
Bu, SQL uygulamalarında çalışabilir, ancak standart nesne koleksiyonuyla çalışmaz - Chris McGrath


Jon Skeet ve Marc Gravell'in daha önce bahsettiği gibi, bir koşulu içeren basit bir şey alabilirsiniz. Ancak, benzer bir sorguda, bir Single () ifadesi almak çok tehlikelidir, çünkü bu sadece 1 sonuç bulmanız anlamına gelir. Daha fazla sonuç olması durumunda, güzel bir istisna alacaksınız :)

Bu yüzden, Single () yerine FirstOrDefault () kullanmayı tercih ederim:

var first = Database.DischargePorts.FirstOrDefault(p => p.PortName.Contains("BALTIMORE"));
var portcode = first != null ? first.PortCode : string.Empty;

8
2018-03-21 06:34



eğer bizim iddia beklentisi Tam olarak bir eşleşme olduğunu, Tek "tehlikeli" değildir - bu "doğru" dir. Veriler hakkında iddia ettiğimiz her şeye ... "herhangi bir sayı", "en az bir", "en fazla", "tam olarak", vb. - Marc Gravell♦
evet, ama bir LIKE Sorgusu muhtemelen tek bir sonuç değildir;) - BitKFu
içeriğe bağlı olarak, bu olabilir ... tamamen sorgunun beklentisine bağlıdır - Marc Gravell♦
Bir "boş" veya "%" araması ne durumda? Bu "B", "BALT" ve "" işlerini halledebilir mi? - BlueChippy


Şey ... bazen kullanmak rahatsız edici olabilir Contains, StartsWith veya EndsWith özellikle değer belirlerken LIKE ör. 'value%' değerini geçerek geliştiriciden StartsWith ifadede işlev. Ben de bu yüzden IQueryable nesneler.

kullanım

// numbers: 11-000-00, 00-111-00, 00-000-11

var data1 = parts.Like(p => p.Number, "%11%");
// result: 11-000-00, 00-111-00, 00-000-11

var data2 = parts.Like(p => p.Number, "11%");
// result: 11-000-00

var data3 = parts.Like(p => p.Number, "%11");
// result: 00-000-11

kod

public static class LinqEx
{
    private static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains");
    private static readonly MethodInfo StartsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
    private static readonly MethodInfo EndsWithMethod = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });

    public static Expression<Func<TSource, bool>> LikeExpression<TSource, TMember>(Expression<Func<TSource, TMember>> property, string value)
    {
        var param = Expression.Parameter(typeof(TSource), "t");
        var propertyInfo = GetPropertyInfo(property);
        var member = Expression.Property(param, propertyInfo.Name);

        var startWith = value.StartsWith("%");
        var endsWith = value.EndsWith("%");

        if (startWith)
            value = value.Remove(0, 1);

        if (endsWith)
            value = value.Remove(value.Length - 1, 1);

        var constant = Expression.Constant(value);
        Expression exp;

        if (endsWith && startWith)
        {
            exp = Expression.Call(member, ContainsMethod, constant);
        }
        else if (startWith) 
        {
            exp = Expression.Call(member, EndsWithMethod, constant);
        }
        else if (endsWith)
        {
            exp = Expression.Call(member, StartsWithMethod, constant);
        }
        else
        {
            exp = Expression.Equal(member, constant);
        }

        return Expression.Lambda<Func<TSource, bool>>(exp, param);
    }

    public static IQueryable<TSource> Like<TSource, TMember>(this IQueryable<TSource> source, Expression<Func<TSource, TMember>> parameter, string value)
    {
        return source.Where(LikeExpression(parameter, value));
    }

    private static PropertyInfo GetPropertyInfo(Expression expression)
    {
        var lambda = expression as LambdaExpression;
        if (lambda == null)
            throw new ArgumentNullException("expression");

        MemberExpression memberExpr = null;

        switch (lambda.Body.NodeType)
        {
            case ExpressionType.Convert:
                memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression;
                break;
            case ExpressionType.MemberAccess:
                memberExpr = lambda.Body as MemberExpression;
                break;
        }

        if (memberExpr == null)
            throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression.");


        var output = memberExpr.Member as PropertyInfo;

        if (output == null)
            throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression.");

        return output;
    }
}

7
2018-02-25 19:07



İle çalışan bir sürümünüz var mı IEnumerable? - Nicke Manarin


Yerel LINQ'da, Contains/StartsWith/EndsWith veya RegExp.

LINQ2SQL kullanım yönteminde SqlMethods.Like()

    from i in db.myTable
    where SqlMethods.Like(i.field, "tra%ata")
    select i

Bu özelliği kullanmak için Assembly: System.Data.Linq (System.Data.Linq.dll içinde) ekleyin.


6
2018-04-06 15:10





Bu kadar basit

string[] users = new string[] {"Paul","Steve","Annick","Yannick"};    
var result = from u in users where u.Contains("nn") select u;

Sonuç -> Annick, Yannick


3
2018-01-01 19:14





Tek bir yöntemi, bir yüklemeyle çağırabilirsiniz:

var portCode = Database.DischargePorts
                   .Single(p => p.PortName.Contains("BALTIMORE"))
                   .PortCode;

2
2018-03-21 06:32