[英]Relax C# LINQ String Comparison (Trim, Case Insensitive, ??)
背景故事:我正在将遗留系统的所有SQL查询重写为LINQ。
数据库并不像我预期的那样干净。 由于许多这些SQL记录包含空格或不同的情况,因此视为相同。
SELECT *
FROM fruit
WHERE name = @fruitname;
如果@fruitname
是apple
,则此查询将匹配任何记录以apple
, _apple
, APPLE_
(其中_
是空格字符)。
但是,这是我的用例中的预期行为。
另一方面,LINQ字符串比较更精确。 这让我感到很恼火,因为这些问题一直存在。
FruitTableAdapter fruitsAdapter = new FruitTableAdapter();
MyGardenDataSet.FruitDataTable fruitsTable = fruitsAdapter.GetData();
// Issue 1: Does not match, '_apple' or 'APPLE_'
var fruits1 = fruitsTable.Where(row=>row.name == fruitname);
// Issue 2: String Comparison with case insensitive (does not match 'APPLE')
var fruits2 = fruitsTable.Where(
row=>row.nameEquals(fruitname, StringComparison.OrdinalIgnoreCase));
// Issue 3: Trailing space with case insensitive
var fruits2 = fruitsTable.Where(
row=>row.name.Trim().Equals(fruitname.Trim(),
StringComparison.OrdinalIgnoreCase));
我不确定但是SQL查询可能存在许多与字符串比较不同的问题。
是否有任何SQL感知StringComparison? 如何在LINQ中实现与SQL相同的字符串比较?
这是一个非常晚的答案。
您可以使用正则Regex
解决您的问题这是我尝试过的,希望它有所帮助
我创建了一个示例类
public class SampleTable
{
public string Name { get; set; }
public SampleTable(string name)
{
Name = name;
}
}
填充样本数据
List<SampleTable> sampleTblList = new List<SampleTable>();
sampleTblList.Add(new SampleTable(" Apple"));
sampleTblList.Add(new SampleTable(" APPLE"));
sampleTblList.Add(new SampleTable("Apple"));
sampleTblList.Add(new SampleTable("apple"));
sampleTblList.Add(new SampleTable("apple "));
sampleTblList.Add(new SampleTable("apmangple"));
解:-
string fruitName = "apple";
List<SampleTable> sortedSampleTblList = sampleTblList.Where(x =>
Regex.IsMatch(fruitName, x.Name, RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase)).ToList();
输出: -
string ans = String.Join(",", sortedSampleTblList.Select(x => x.Name.Replace(" ","_")).ToArray());
Console.Write(ans);
_Apple,_APPLE,Apple,apple,apple_
fruitsTable.Where(row => row.name.Trim().Equals(fruitname, StringComparison.OrdinalIgnoreCase));
应该做你需要的,但我很困惑,因为你在问题3中列出的几乎相同。你没有意识到它是有效的,因为你正在重用fruits2
?
这个小NUnit测试正在通过
[Test]
public void FruitTest()
{
var fruitsTable = new List<string> { " Apple", " APPLE", "Apple", "apple", "apple ", " apple", "APPLE " };
var fruitname = "apple ".Trim();
var fruits = fruitsTable.Where(row => row.Trim().Equals(fruitname, StringComparison.OrdinalIgnoreCase));
Assert.AreEqual(fruitsTable.Count(), fruits.Count());
}
这是一个很好的字符串扩展方法,它基于类似于套管StackOverflow的类似问题的解决方案
请记住,我们希望在修剪场景中允许NULL字符串,因此在检查空值后,此扩展将对Trimmed字符串执行Case Insensitive比较
public static class StringExtension
{
// Trim strings and compare values without casing
public static bool SqlCompare(this string source, string value)
{
// Handle nulls before trimming
if (!string.IsNullOrEmpty(source))
source = source.Trim();
if (!string.IsNullOrEmpty(value))
value = value.Trim();
// Compare strings (case insensitive)
return string.Equals(source, value, StringComparison.CurrentCultureIgnoreCase);
}
}
以下是在LINQ语句中使用Extension的方法:
(SysUserDisplayFavorites表由带有空格填充结果的char()字段组成。这些字段将被修剪并与displayFavorite对象中用户提供的值进行比较(不区分大小写)
var defaultFavorite = _context.SysUserDisplayFavorites
.Where(x => x.UserId.SqlCompare(displayFavorite.UserId))
.Where(x => x.ModuleCode.SqlCompare(displayFavorite.ModuleCode))
.Where(x => x.ActivityCode.SqlCompare(displayFavorite.ActivityCode))
.Where(x => x.ActivityItemCode.SqlCompare(displayFavorite.ActivityItemCode))
.Where(x => x.IsDefault);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.