背景故事:我正在将遗留系统的所有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相同的字符串比较?
答案 0 :(得分:0)
这是一个很晚的答案。
您可以使用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_
答案 1 :(得分:0)
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());
}
答案 2 :(得分:0)
这是一个很好的String Extension方法,它基于有关大小写StackOverflow
的类似问题的解决方案请记住,我们希望在调整场景中允许使用NULL字符串,因此此扩展将在检查空值之后对Trimmed字符串进行不区分大小写的比较
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语句中使用扩展的方法:
(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);