放松C#LINQ字符串比较(修剪,不区分大小写,??)

时间:2015-11-25 09:50:58

标签: c# string linq

问题

  

背景故事:我正在将遗留系统的所有SQL查询重写为LINQ。

数据库并不像我预期的那样干净。由于许多SQL记录包含空格或不同的情况,因此视为相同。

SELECT * 
FROM fruit 
WHERE name = @fruitname;

如果@fruitnameapple,则此查询会将所有记录与apple_appleAPPLE_匹配(其中_为空白字符)。

但是,这是我用例中的预期行为。

另一方面,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相同的字符串比较?

3 个答案:

答案 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);