繁体   English   中英

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

[英]Relax C# LINQ String Comparison (Trim, Case Insensitive, ??)

问题

背景故事:我正在将遗留系统的所有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相同的字符串比较?

这是一个非常晚的答案。

您可以使用正则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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM