Linq içinde SQL Like% nasıl yapılır?


385

Linq dönüşmeye çalışıyorum SQL bir yordam var:

SELECT O.Id, O.Name as Organization
FROM Organizations O
JOIN OrganizationsHierarchy OH ON O.Id=OH.OrganizationsId
where OH.Hierarchy like '%/12/%'

En çok ilgilendiğim çizgi:

where OH.Hierarchy like '%/12/%'

/ 1/3/12 / gibi hiyerarşisini depolayan bir sütun var, bu yüzden sadece aramak için% / 12 /% kullanın.

Benim sorum, Linq veya .NET yüzde işaretini kullanmaya eşdeğerdir?


1
Sorunuz en az benzer operatör etiketi 5için oy kullanıyor . Eşanlamlı olarak sql-like önermenizi rica edebilir miyim ?
Kermit

Yanıtlar:


550
.Where(oh => oh.Hierarchy.Contains("/12/"))

Ayrıca kullanabilir .StartsWith()veya .EndsWith().


4
StartsWith () veya EndsWith () kullanmak bir sorguyu tetikler mi? Yani, kod bir sorguya çevrilecek mi veya sonuçları DB'den alındıktan sonra nesnede filtrelenecek?
Acemi

5
Hayır. StarttsWith () ve EndsWith () yüklemin / filtrenin bir parçasıdır. İcra ertelenmeye devam ediyor.
andleer

2
NullReferenceException: Nesne başvurusu bir nesnenin örneğine ayarlanmadı. Bu yüzden benim durumumda a.Address1.StartsWith (Adres1) ve a.Address1 boş olduğunda beğenmez
MikeT

11
StartsWith("abc")dönüştürülmüş olur LIKE 'abc%'ve EndsWith("abc")hiç cnoverted edilirLIKE '%abc'
Simon_Weaver

20
Bunun neden harflerle bir kullanım vakası için çalışmadığını anlayamadım, sonra aptallığımı fark ettim ... .ToLower().Contains()vakayı görmezden gelmek istiyorsanız vb. Bunu isteyip istemediğiniz elbette büyük / küçük harf duyarsız harmanlama ile bir DB LIKE taklit etmeye bağlıdır bağlıdır.
Adam Knights

251

Bunu kullan:

from c in dc.Organization
where SqlMethods.Like(c.Hierarchy, "%/12/%")
select *;

22
like komutu tarafından sağlanan daha karmaşık desen eşleşmesini kullanmak istiyorsanız bu gerçekten yararlıdır. Örneğin, herhangi bir iki sayıyı (12 yerine) kontrol etmek istiyorsanız, şu ifadeyi kullanabilirsiniz: SqlMethods.Like (c.Hierarchy, "% / [0-9] [0-9] /%") Ayrıca , bkz. msdn.microsoft.com/en-us/library/aa933232(SQL.80).aspx
viggity

bu, güç kullanıcılarının pahalı başlangıç% 'sini önceden harcamalarına izin vermek istiyorsanız da çok kullanışlıdır, burada StartsWith veya Contains kullanıldığında güç kullanıcısına bu esneklik verilmez
Simon_Weaver

8
SqlMethods"Nokta notasyonu" kullanarak nasıl kullanılır?
dan-gph

12
Ad System.Data.Linq.SqlClientalanını eklemeniz gerektiğini unutmayın .
johna

1
System.Data.Linq ekleyebilmeme rağmen System.Data.Linq.SqlClient bulamadım. Onaylanmadı mı?
Burak Karakuş

41

Linq-to-SQL * kullandığınızı varsayıyorum (aşağıdaki nota bakın). Öyleyse, SQL LIKE işlecini kullanan SQL oluşturmak için string.Contains, string.StartsWith ve string.EndsWith öğelerini kullanın.

from o in dc.Organization
join oh in dc.OrganizationsHierarchy on o.Id equals oh.OrganizationsId
where oh.Hierarchy.Contains(@"/12/")
select new { o.Id, o.Name }

veya

from o in dc.Organization
where o.OrganizationsHierarchy.Hierarchy.Contains(@"/12/")
select new { o.Id, o.Name }

Not: * = .net 3.5 içinde ADO.Net Entity Framework (EF / L2E) kullanıyorsanız, Linq-to-SQL ile aynı çeviriyi yapmayacağını unutmayın. L2S düzgün bir çeviri yapsa da, L2E v1 (3.5), nerede yan tümcenizde veya birleştirme filtrelerinde başka bir daha iyi ayırıcı yoksa, sorguladığınız tabloda tam tablo taramasını zorlayacak bir t-sql ifadesine dönüşecektir.
Güncelleme: Bu EF / L2E v4 (.net 4.0) ile düzeltildi, bu yüzden L2S gibi bir SQL LIKE üretecek.


İşaretlerle işaretlerinden kaçmaya gerek yok, @ancak bunun sadece takip etmek için iyi bir kongre olabileceğini anlıyorum.
andleer

27

VB.NET kullanıyorsanız, yanıt "*" olacaktır. İşte nerede fıkra gibi görünecek ...

Where OH.Hierarchy Like '*/12/*'

Not: "*" Sıfır veya daha fazla karakterle eşleşir. İşte Like işleci için msdn makalesi .


VB Like operatörü L2S çağrılarına çevriliyor mu? (Hiçbir fikrim yok.)
andleer

8
Evet, VB Like işleci bir LINQ sorgu ifadesinde kullanıldığında benzer SQL sürümüne çevrilir. Ayrıca, VB Like işleci sorgu ifadeleriyle sınırlı değildir.
robertz

1
LINQ operasyonları dışında var olduğunu gördüm. İyi şeyler. +1
andleer

9

Benim için de çalışıyor

var result = from c in SampleList
where c.LongName.IndexOf(SearchQuery) >= 0
select c;

1
Bu kabul edilen cevap olmalı. IndexOf, sql cinsinden CHARINDEX anlamına gelir. Bu muhtemelen LIKE'den daha hızlı olabilir. Ancak bunun dışında, '% some% thing%' gibi arama sorguları oluşturma olanağı sağlar. İçindekilerle yapılamayacak olan 'bazıların' 'şeyden' önce bulunması gereken yerler
Ruard van Elburg

İhtiyacım olan cevaplar 8 yaşındayken ve kabul edilen cevabın altında birkaç katman sıkıştığında seviyorum. Basitçe söylemek gerekirse, bu işe yaradı .Contains (@ "/ 12 /") ve diğer benzer cevaplar işe yaramadı. Çok takdir!
IdusOrtus

4

Bu kodu kullan

try
{
    using (DatosDataContext dtc = new DatosDataContext())
    {
        var query = from pe in dtc.Personal_Hgo
                    where SqlMethods.Like(pe.nombre, "%" + txtNombre.Text + "%")
                    select new
                    {
                        pe.numero
                        ,
                        pe.nombre
                    };
        dgvDatos.DataSource = query.ToList();
    }
}
catch (Exception ex)
{
    string mensaje = ex.Message;
}

4

.NET core artık EF.Functions.Like


OP'nin problemini çözmek için bunu nasıl kullanacağınızı açıklayabilir misiniz?
Robert Columbia

yani yani LP'nin cevabı, sadece SqlMethods'ın çekirdek versiyonudur.Like
kofifus

Bu yanıt, bu işlevin nasıl kullanılacağına ilişkin eyleme dönüştürülebilir bir örnek içermelidir.
FoxDeploy

3

Sayısal dizelerle eşleşmemeniz durumunda, ortak duruma sahip olmak her zaman iyidir:

.Where(oh => oh.Hierarchy.ToUpper().Contains(mySearchString.ToUpper()))

2

Her zaman bunu yaparım:

from h in OH
where h.Hierarchy.Contains("/12/")
select h

Ben benzer ifade kullanmıyorum biliyorum ama bu arka planda iyi çalışır bu benzer bir ifade ile bir sorguya çevrilmiş olmasıdır.


Cevabınız kabul edilen cevaptan (7 yıl önce cevaplandı) veya diğer cevaplardan nasıl farklı? Ne katıyor?
David Ferenczy Rogožan

1
@DawidFerenczy Bu cevap "foo in bar" sorgu sözdizimi ile çalışır ve kabul edilen yanıt vermez.
nasch

1

Bunu dene, bu benim için iyi çalışıyor

from record in context.Organization where record.Hierarchy.Contains(12) select record;


0

İçerir Linq kullanılır, Tıpkı Like SQL'de kullanılır.

string _search="/12/";

. . .

.Where(s => s.Hierarchy.Contains(_search))

Linq içinde SQL betiğinizi aşağıdaki gibi yazabilirsiniz:

 var result= Organizations.Join(OrganizationsHierarchy.Where(s=>s.Hierarchy.Contains("/12/")),s=>s.Id,s=>s.OrganizationsId,(org,orgH)=>new {org,orgH});

0

LINQ bir "SQL Like" yöntemi için bir yol arayan burada benim gibi takla olanlar için, çok iyi çalışan bir şey var.

Ben sütun harmanlamasını değiştirmek için herhangi bir şekilde Veritabanı değiştiremiyorum bir durumda değilim. Bu yüzden LINQ'umda bunu yapmanın bir yolunu bulmalıyım.

Yardımcı yöntemi kullanıyorum SqlFunctions.PatIndex cadı gerçek SQL LIKE operatörüne benzer şekilde kullanıyorum.

Öncelikle, arama değerinde olası tüm aksanları (az önce öğrendiğim bir kelime) numaralandırmam gerekiyor:

déjà     => d[éèêëeÉÈÊËE]j[aàâäAÀÂÄ]
montreal => montr[éèêëeÉÈÊËE][aàâäAÀÂÄ]l
montréal => montr[éèêëeÉÈÊËE][aàâäAÀÂÄ]l

ve sonra örnek için LINQ'da:

var city = "montr[éèêëeÉÈÊËE][aàâäAÀÂÄ]l";
var data = (from loc in _context.Locations
                     where SqlFunctions.PatIndex(city, loc.City) > 0
                     select loc.City).ToList();

Bu yüzden ihtiyaçlarım için bir Yardımcı / Genişletme yöntemi yazdım

   public static class SqlServerHelper
    {

        private static readonly List<KeyValuePair<string, string>> Diacritics = new List<KeyValuePair<string, string>>()
        {
            new KeyValuePair<string, string>("A", "aàâäAÀÂÄ"),
            new KeyValuePair<string, string>("E", "éèêëeÉÈÊËE"),
            new KeyValuePair<string, string>("U", "uûüùUÛÜÙ"),
            new KeyValuePair<string, string>("C", "cçCÇ"),
            new KeyValuePair<string, string>("I", "iîïIÎÏ"),
            new KeyValuePair<string, string>("O", "ôöÔÖ"),
            new KeyValuePair<string, string>("Y", "YŸÝýyÿ")
        };

        public static string EnumarateDiacritics(this string stringToDiatritics)
        {
            if (string.IsNullOrEmpty(stringToDiatritics.Trim()))
                return stringToDiatritics;

            var diacriticChecked = string.Empty;

            foreach (var c in stringToDiatritics.ToCharArray())
            {
                var diac = Diacritics.FirstOrDefault(o => o.Value.ToCharArray().Contains(c));
                if (string.IsNullOrEmpty(diac.Key))
                    continue;

                //Prevent from doing same letter/Diacritic more than one time
                if (diacriticChecked.Contains(diac.Key))
                    continue;

                diacriticChecked += diac.Key;

                stringToDiatritics = stringToDiatritics.Replace(c.ToString(), "[" + diac.Value + "]");
            }

            stringToDiatritics = "%" + stringToDiatritics + "%";
            return stringToDiatritics;
        }
    }

Herhangi birinizin bu yöntemi geliştirmek için öneriniz varsa, lütfen sizi duymak isterim.


Örneğiniz temel olarak ev yapımı bir aksan duyarsız harmanlamadır. Bir keresinde, her sorgunun otomatik olarak uygun bir harmanlama yapması için bir filtreden geçtiği bir projeyle uğraşmak zorunda kaldım. Genellikle daha iyi bir yaklaşım için lütfen stackoverflow.com/a/2461550/1736944 adresine bakın . Veritabanına, tabloya ve / veya alana uygun olarak uygun harmanlamayı atayın. (Düzgün bir harmanlama olmadan çalışmak saf bir işkence)
9Rune5

0

Geç saatlere kadar, ancak SQL Like tarzı joker karakterleri kullanarak Dize karşılaştırmaları yapabilmek için bunu birlikte attım:

public static class StringLikeExtensions
{
    /// <summary>
    /// Tests a string to be Like another string containing SQL Like style wildcards
    /// </summary>
    /// <param name="value">string to be searched</param>
    /// <param name="searchString">the search string containing wildcards</param>
    /// <returns>value.Like(searchString)</returns>
    /// <example>value.Like("a")</example>
    /// <example>value.Like("a%")</example>
    /// <example>value.Like("%b")</example>
    /// <example>value.Like("a%b")</example>
    /// <example>value.Like("a%b%c")</example>
    /// <remarks>base author -- Ruard van Elburg from StackOverflow, modifications by dvn</remarks>
    /// <remarks>converted to a String extension by sja</remarks>
    /// <seealso cref="/programming/1040380/wildcard-search-for-linq"/>
    public static bool Like(this String value, string searchString)
    {
        bool result = false;

        var likeParts = searchString.Split(new char[] { '%' });

        for (int i = 0; i < likeParts.Length; i++)
        {
            if (likeParts[i] == String.Empty)
            {
                continue;   // "a%"
            }

            if (i == 0)
            {
                if (likeParts.Length == 1) // "a"
                {
                    result = value.Equals(likeParts[i], StringComparison.OrdinalIgnoreCase);
                }
                else // "a%" or "a%b"
                {
                    result = value.StartsWith(likeParts[i], StringComparison.OrdinalIgnoreCase);
                }
            }
            else if (i == likeParts.Length - 1) // "a%b" or "%b"
            {
                result &= value.EndsWith(likeParts[i], StringComparison.OrdinalIgnoreCase);
            }
            else // "a%b%c"
            {
                int current = value.IndexOf(likeParts[i], StringComparison.OrdinalIgnoreCase);
                int previous = value.IndexOf(likeParts[i - 1], StringComparison.OrdinalIgnoreCase);
                result &= previous < current;
            }
        }

        return result;
    }

    /// <summary>
    /// Tests a string containing SQL Like style wildcards to be ReverseLike another string 
    /// </summary>
    /// <param name="value">search string containing wildcards</param>
    /// <param name="compareString">string to be compared</param>
    /// <returns>value.ReverseLike(compareString)</returns>
    /// <example>value.ReverseLike("a")</example>
    /// <example>value.ReverseLike("abc")</example>
    /// <example>value.ReverseLike("ab")</example>
    /// <example>value.ReverseLike("axb")</example>
    /// <example>value.ReverseLike("axbyc")</example>
    /// <remarks>reversed logic of Like String extension</remarks>
    public static bool ReverseLike(this String value, string compareString)
    {
        bool result = false;

        var likeParts = value.Split(new char[] {'%'});

        for (int i = 0; i < likeParts.Length; i++)
        {
            if (likeParts[i] == String.Empty)
            {
                continue;   // "a%"
            }

            if (i == 0)
            {
                if (likeParts.Length == 1) // "a"
                {
                    result = compareString.Equals(likeParts[i], StringComparison.OrdinalIgnoreCase);
                }
                else // "a%" or "a%b"
                {
                    result = compareString.StartsWith(likeParts[i], StringComparison.OrdinalIgnoreCase);
                }
            }
            else if (i == likeParts.Length - 1) // "a%b" or "%b"
            {
                result &= compareString.EndsWith(likeParts[i], StringComparison.OrdinalIgnoreCase);
            }
            else // "a%b%c"
            {
                int current = compareString.IndexOf(likeParts[i], StringComparison.OrdinalIgnoreCase);
                int previous = compareString.IndexOf(likeParts[i - 1], StringComparison.OrdinalIgnoreCase);
                result &= previous < current;
            }
        }

        return result;
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.