Apakah ada cara untuk membandingkan string dalam ekspresi C # LINQ yang mirip dengan LIKE
operator SQL ?
Misalkan saya memiliki daftar string. Di daftar ini saya ingin mencari string. Di SQL, saya bisa menulis:
SELECT * FROM DischargePort WHERE PortName LIKE '%BALTIMORE%'
Alih-alih di atas, kueri menginginkan sintaks linq.
using System.Text.RegularExpressions;
…
var regex = new Regex(sDischargePort, RegexOptions.IgnoreCase);
var sPortCode = Database.DischargePorts
.Where(p => regex.IsMatch(p.PortName))
.Single().PortCode;
Sintaks LINQ saya di atas tidak berfungsi. Apa yang salah?
Jawaban:
Biasanya Anda menggunakan
String.StartsWith
/EndsWith
/Contains
. Sebagai contoh:var portCode = Database.DischargePorts .Where(p => p.PortName.Contains("BALTIMORE")) .Single() .PortCode;
Saya tidak tahu apakah ada cara untuk melakukan ekspresi reguler yang tepat melalui LINQ ke SQL. (Perhatikan bahwa ini benar-benar bergantung pada penyedia mana yang Anda gunakan - akan baik-baik saja di LINQ ke Objek; ini masalah apakah penyedia dapat mengonversi panggilan ke dalam format kueri aslinya, misalnya SQL.)
EDIT: Seperti yang dikatakan BitKFu,
Single
harus digunakan saat Anda mengharapkan tepat satu hasil - ketika itu adalah kesalahan untuk itu tidak terjadi. Pilihan dariSingleOrDefault
,FirstOrDefault
atauFirst
harus digunakan tergantung pada persis apa yang diharapkan.sumber
Single()
,SingleOrDefault()
akan menjadi langkah saya berikutnya, kecuali kita memahami konteks lengkapnya ...Regex? tidak. Tetapi untuk kueri itu Anda bisa menggunakan:
string filter = "BALTIMORE"; (blah) .Where(row => row.PortName.Contains(filter)) (blah)
Jika Anda benar - benar menginginkan SQL
LIKE
, Anda dapat menggunakanSystem.Data.Linq.SqlClient.SqlMethods.Like(...)
, yang dipetakan LINQ-ke-SQLLIKE
di SQL Server.sumber
Yah ... kadang-kadang mungkin tidak nyaman untuk digunakan
Contains
,StartsWith
atauEndsWith
terutama ketika mencari nilai menentukanLIKE
pernyataan misalnya lulus 'nilai%' mengharuskan dari pengembang untuk menggunakanStartsWith
fungsi dalam ekspresi. Jadi saya memutuskan untuk menulis ekstensi untukIQueryable
objek.Pemakaian
// 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
Kode
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; } }
sumber
IEnumerable
?Seperti yang telah disebutkan Jon Skeet dan Marc Gravell, Anda dapat dengan mudah mengambil kondisi cadangan. Tetapi dalam kasus kueri like Anda, sangat berbahaya untuk mengambil pernyataan Single (), karena itu menyiratkan bahwa Anda hanya menemukan 1 hasil. Jika lebih banyak hasil, Anda akan menerima pengecualian yang bagus :)
Jadi saya lebih suka menggunakan FirstOrDefault () daripada Single ():
var first = Database.DischargePorts.FirstOrDefault(p => p.PortName.Contains("BALTIMORE")); var portcode = first != null ? first.PortCode : string.Empty;
sumber
Dalam LINQ asli, Anda dapat menggunakan kombinasi
Contains/StartsWith/EndsWith
atau RegExp.Dalam metode penggunaan LINQ2SQL
SqlMethods.Like()
from i in db.myTable where SqlMethods.Like(i.field, "tra%ata") select i
tambahkan Assembly: System.Data.Linq (di System.Data.Linq.dll) untuk menggunakan fitur ini.
sumber
StartsWith()
,,Contains()
dll, tidak berfungsi dengan Linq2SQL (setidaknya saya mendapatkan "Ekspresi LINQ… tidak dapat diterjemahkan…" dan instruksi untuk menggunakan ToList () untuk "evaluasi klien" —yang saya ' Saya sudah melakukan. Catatan, di EF Core, dipindahkan keEF.Functions.Like()
.Where(e => e.Value.StartsWith("BALTIMORE"))
Ini berfungsi seperti "LIKE" dari SQL ...
sumber
Sesederhana ini
string[] users = new string[] {"Paul","Steve","Annick","Yannick"}; var result = from u in users where u.Contains("nn") select u;
Hasil -> Annick, Yannick
sumber
Anda dapat memanggil metode tunggal dengan predikat:
var portCode = Database.DischargePorts .Single(p => p.PortName.Contains("BALTIMORE")) .PortCode;
sumber
Idealnya Anda harus menggunakan
StartWith
atauEndWith
.Berikut ini contohnya:
DataContext dc = new DCGeneral(); List<Person> lstPerson= dc.GetTable<Person>().StartWith(c=> c.strNombre).ToList(); return lstPerson;
sumber
public static class StringEx { public static bool Contains(this String str, string[] Arr, StringComparison comp) { if (Arr != null) { foreach (string s in Arr) { if (str.IndexOf(s, comp)>=0) { return true; } } } return false; } public static bool Contains(this String str,string[] Arr) { if (Arr != null) { foreach (string s in Arr) { if (str.Contains(s)) { return true; } } } return false; } } var portCode = Database.DischargePorts .Single(p => p.PortName.Contains( new string[] {"BALTIMORE"}, StringComparison.CurrentCultureIgnoreCase) )) .PortCode;
sumber
Cukup tambahkan ke metode ekstensi objek string.
public static class StringEx { public static bool Contains(this String str, string[] Arr, StringComparison comp) { if (Arr != null) { foreach (string s in Arr) { if (str.IndexOf(s, comp)>=0) { return true; } } } return false; } public static bool Contains(this String str,string[] Arr) { if (Arr != null) { foreach (string s in Arr) { if (str.Contains(s)) { return true; } } } return false; } }
pemakaian:
use namespase that contains this class; var sPortCode = Database.DischargePorts .Where(p => p.PortName.Contains(new string [] {"BALTIMORE"}, StringComparison.CurrentCultureIgnoreCase) ) .Single().PortCode;
sumber
List<Categories> categoriess; private void Buscar() { try { categoriess = Contexto.Categories.ToList(); categoriess = categoriess.Where(n => n.CategoryID >= Convert.ToInt32(txtCatID.Text) && n.CategoryID <= Convert.ToInt32(txtCatID1.Text) && (n.CategoryName.Contains(txtCatName.Text)) ).ToList();
sumber
@adobrzyc memiliki
LIKE
fungsi khusus yang hebat ini - Saya hanya ingin membagikanIEnumerable
versinya.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) }); private static 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).Compile(); } public static IEnumerable<TSource> Like<TSource, TMember>(this IEnumerable<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; } }
sumber