SQL의 LIKE
연산자 와 유사한 C # LINQ 식의 문자열을 비교할 수있는 방법이 있습니까?
문자열 목록이 있다고 가정합니다. 이 목록에서 문자열을 검색하고 싶습니다. SQL에서 다음과 같이 작성할 수 있습니다.
SELECT * FROM DischargePort WHERE PortName LIKE '%BALTIMORE%'
위의 대신 쿼리는 linq 구문을 원합니다.
using System.Text.RegularExpressions;
…
var regex = new Regex(sDischargePort, RegexOptions.IgnoreCase);
var sPortCode = Database.DischargePorts
.Where(p => regex.IsMatch(p.PortName))
.Single().PortCode;
위의 LINQ 구문이 작동하지 않습니다. 내가 뭘 잘못 했니?
답변
일반적으로 String.StartsWith
/ EndsWith
/ 를 사용 Contains
합니다. 예를 들면 :
var portCode = Database.DischargePorts
.Where(p => p.PortName.Contains("BALTIMORE"))
.Single()
.PortCode;
그래도 LINQ to SQL을 통해 적절한 정규식을 수행하는 방법이 있는지 모르겠습니다. (실제로 사용중인 공급자에 따라 다릅니다. LINQ to Objects에서는 괜찮습니다. 공급자가 호출을 SQL과 같은 네이티브 쿼리 형식으로 변환 할 수 있는지 여부는 문제입니다.)
편집 : BitKFu가 말했듯이 정확히 하나의 결과 Single
를 기대할 때 사용해야합니다 -그렇지 않은 오류 일 때. , 또는의 옵션은 정확히 예상되는 것에 따라 사용해야합니다 .SingleOrDefault
FirstOrDefault
First
답변
정규식? 아니. 그러나 해당 쿼리의 경우 다음을 사용할 수 있습니다.
string filter = "BALTIMORE";
(blah) .Where(row => row.PortName.Contains(filter)) (blah)
당신이 경우 실제로 SQL을 원하는 LIKE
, 당신이 사용할 수있는 System.Data.Linq.SqlClient.SqlMethods.Like(...)
LINQ – 투 – SQL에 매핑되는 LIKE
SQL Server의.
답변
글쎄 … 때로는 사용하기가 불편할 수 있습니다 Contains
. StartsWith
또는 EndsWith
특히 값을 검색 할 때 LIKE
예를 들어 전달 된 ‘value %’는 개발자가 StartsWith
표현식에서 함수 를 사용해야 합니다. 그래서 나는 IQueryable
객체에 대한 확장을 작성하기로 결정했습니다 .
용법
// 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
암호
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;
}
}
답변
Jon Skeet과 Marc Gravell이 이미 언급했듯이 포함 조건을 간단히 취할 수 있습니다. 그러나 같은 쿼리의 경우 Single () 문을 사용하는 것은 매우 위험합니다. 그 이유는 결과가 1 개뿐임을 의미하기 때문입니다. 더 많은 결과의 경우 멋진 예외를 받게됩니다. 🙂
따라서 Single () 대신 FirstOrDefault ()를 사용하는 것이 좋습니다.
var first = Database.DischargePorts.FirstOrDefault(p => p.PortName.Contains("BALTIMORE"));
var portcode = first != null ? first.PortCode : string.Empty;
답변
네이티브 LINQ에서는 Contains/StartsWith/EndsWith
또는 RegExp의 조합을 사용할 수 있습니다 .
LINQ2SQL 사용 방법 SqlMethods.Like()
from i in db.myTable
where SqlMethods.Like(i.field, "tra%ata")
select i
이 기능을 사용하려면 Assembly : System.Data.Linq (System.Data.Linq.dll에 있음)를 추가합니다.
답변
.Where(e => e.Value.StartsWith("BALTIMORE"))
이것은 SQL의 “LIKE”처럼 작동합니다.
답변
이처럼 간단
string[] users = new string[] {"Paul","Steve","Annick","Yannick"};
var result = from u in users where u.Contains("nn") select u;
결과-> Annick, Yannick