[英]Linq & String.ToLower() strange behavior
I have a query on the server side that returns a list of distinct cities from a zipcode table. 我在服务器端有一个查询,它从一个zipcode表返回一个不同城市的列表。
I'm using WCF RIA Service. 我正在使用WCF RIA服务。
The following query successfully returns 228 cities when provincename == ""
provincename == ""
时,以下查询成功返回228个城市
public IQueryable<CityPM> GetCities(string provinceName)
{
return this.ObjectContext.ZipCodes.Where(z => z.Province.Contains(provinceName))
.GroupBy(z => z.City)
.Select(g => g.FirstOrDefault())
.Select(zc => new CityPM() { ID = zc.ID, Name = zc.City });
}
but if I use ToLower() method as below, the query returns 0 cities when provincename == ""
. 但如果我使用如下的ToLower()方法,则当
provincename == ""
时,查询返回0个城市。
public IQueryable<CityPM> GetCities(string provinceName)
{
return this.ObjectContext.ZipCodes.Where(z => z.Province.ToLower().Contains(provinceName.ToLower()))
.GroupBy(z => z.City)
.Select(g => g.FirstOrDefault())
.Select(zc => new CityPM() { ID = zc.ID, Name = zc.City });
}
Why isn't the query returning anything? 为什么查询不返回任何内容?
Try checking the SQL generated, either by using DB management tools, or calling .ToTraceString() at the end of the query expression. 尝试使用数据库管理工具检查生成的SQL,或者在查询表达式的末尾调用.ToTraceString()。
Reference: http://blog.aggregatedintelligence.com/2010/06/viewing-entity-framework-generated-sql.html 参考: http : //blog.aggregatedintelligence.com/2010/06/viewing-entity-framework-generated-sql.html
We use ToTraceString at work using an extension: 我们在使用扩展时使用ToTraceString:
public static IQueryable<T> TraceSql<T>(this IQueryable<T> query)
{
var sql = ((System.Data.Objects.ObjectQuery)query).ToTraceString();
// do whatever logging of sql you want here, eg (for web)
// (view by visiting trace.axd within your site)
HttpContext.Current.Trace.Write("sql", sql);
return query;
}
It can then be used as follows: 然后可以使用如下:
public IQueryable<CityPM> GetCities(string provinceName)
{
return this.ObjectContext.ZipCodes.Where(z => z.Province.ToLower().Contains(provinceName.ToLower()))
.GroupBy(z => z.City)
.Select(g => g.FirstOrDefault())
.Select(zc => new CityPM() { ID = zc.ID, Name = zc.City })
.TraceSql();
}
Please forgive me for any typos, this is from memory. 请原谅我的任何错别字,这是来自记忆。 Hopefully it will help you understand your problem.
希望它能帮助您理解您的问题。
I was having the same problem and I found out why this is occurring. 我遇到了同样的问题,我发现了为什么会这样。 Running SQL Profiler I saw that the WHERE statements generated from LINQ to SQL are very different in each case.
运行SQL事件探查器我发现从LINQ到SQL生成的WHERE语句在每种情况下都是非常不同的。
.Where(z => z.Province.Contains(provinceName))
would render in SQL as: 将在SQL中呈现为:
WHERE [Province] LIKE N'%%'
As you have experienced, LIKE '%%'
would match any non null results. 正如您所经历的那样,
LIKE '%%'
将匹配任何非null结果。
. 。
However, 然而,
.Where(z => z.Province.ToLower().Contains(provinceName.ToLower()))
would render in SQL as: 将在SQL中呈现为:
WHERE ( CAST( CHARINDEX(LOWER(N''), LOWER([Province])) AS int)) > 0
This is very different than LIKE '%%'
. 这与
LIKE '%%'
非常不同。 SQL is essentially looking to see what character string.Empty
is in the string Province . SQL基本上是在查看字符串省中的字符串
string.Empty
。 The result of the CHARINDEX
on an empty string is 0 which is why there are no results being returned. CHARINDEX
在空字符串上的结果为0,这就是没有返回结果的原因。
. 。
This is a little hackish but it'll work. 这有点hackish但它会起作用。 Only call
.ToLower()
if the the string is not empty. 如果字符串不为空,则仅调用
.ToLower()
。 The following code is an example of something that should work for you. 以下代码是适合您的一些示例。
public IQueryable<CityPM> GetCities(string provinceName)
{
var lowerProvinceName = String.IsNullOrEmpty(provinceName) ? string.Empty : provinceName.ToLower();
return this.ObjectContext.ZipCodes.Where(z => z.Province.ToLower().Contains(lowerProvinceName))
.GroupBy(z => z.City)
.Select(g => g.FirstOrDefault())
.Select(zc => new CityPM() { ID = zc.ID, Name = zc.City });
}
By structuring your code like this, LINQ to SQL will render as LIKE '%%'
if provinceName is an empty string, otherwise it'll render as CHARINDEX
. 通过像这样构造你的代码,如果provinceName是一个空字符串, LINQ to SQL将呈现为
LIKE '%%'
,否则它将呈现为CHARINDEX
。 It also helps if there is a null passed in. 如果传入null,它也会有所帮助。
This worked for me, give it a try if you like it 这对我有用,如果你喜欢,试一试
context.MyEntities.Where(p => p.Email.ToUpper().Equals(muser.Email.ToUpper())); context.MyEntities.Where(p => p.Email.ToUpper()。Equals(muser.Email.ToUpper()));
Note: I am querying it against Oracle 注意:我正在查询Oracle
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.