如何使用LINQ仅返回列的第一个字符在某个范围内的行?

时间:2016-04-29 14:26:21

标签: c# sql-server linq

我想使用LINQ将我从SQL Server数据库返回的行数限制为主键(WordId)第一个字符在A到E范围内的行。这是我目前的方式使用此LINQ执行此操作:

var words = db.WordForm
            .Where(wf => string.Compare(wf.WordId.Substring(0, 1), "A") >= 0 && 
                         string.Compare(wf.WordId.Substring(0, 1), "E") <= 0)
            .ToListAsync();

有人能告诉我这是最好的方法吗?还是有另一种方式使用LINQ?

4 个答案:

答案 0 :(得分:3)

您可以使用SqlFunctions.Ascii,此函数返回字符表达式最左侧字符的 ASCII 代码值,因此您可以像这样使用它:

int asciiA = Encoding.ASCII.GetBytes("A")[0];
int asciiE = Encoding.ASCII.GetBytes("E")[0];

var words = db.WordForm.Where(wf => SqlFunctions.Ascii(wf.WordId.ToUpper()) >= asciiA &&
                                    SqlFunctions.Ascii(wf.WordId.ToUpper()) <= asciiE).ToListAsync();

答案 1 :(得分:1)

刚刚使用HashSet<T>测试了不同的方法,没有它。如果我们有&lt;使用List<T>.Contains()方法的20k记录就足够了:

        var db = new List<MyClass>()
        {
            new MyClass() { WordId = "gds134" }, new MyClass() { WordId = "ads134" },
            new MyClass() { WordId = "Cds134" }, new MyClass() { WordId = "Hds134" },
            new MyClass() { WordId = "eds134" }, new MyClass() { WordId = "eds135" },
        };

        var lettersList = new List<char>() { 'a', 'b', 'c', 'd', 'e', 'A', 'B', 'C', 'D', 'E' };

        var result = db.Where(x => lettersList.Contains(x.WordId.First()));

        foreach(var item in result) Console.WriteLine(item.WordId);

输出:

ads134
Cds134
eds134
eds135

P.S。 另一个例子(包括简单的性能诊断):

http://rextester.com/KCNX61550

答案 2 :(得分:1)

  

有人能告诉我这是最好的方法吗?或者在那里   使用LINQ的另一种方式?

有人肯定可以告诉你。但这将是基于有限信息的意见。你所拥有的将会发挥作用并发挥作用。你在用EF吗? LINQ是否转换为SQL查询?如果是这种情况,您肯定希望调试并查看正在生成的SQL。

如何调试SQL:

private EntitiesContext _context;
private EntitiesContext EntitiesContext
        {
            get
            {
                if (_context == null)
                {
                    _context = new EntitiesContext();
                     _context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s); //For debugging the SQL made by EF
                }
                return _context;
            }
            set { _context = value; }
        }

如果您正在使用已创建的列表,则可以考虑使用regex。如果应用于EF上下文,我怀疑这将转化得非常糟糕。

答案 3 :(得分:0)

在代码中没有一种方法可以使用“A thru E”,您需要创建一个列表或字符串数​​组来表示您要检查的起始字母。

请看下面的示例解决方案:

我在代码中创建了WordForm对象;很明显,你的数据库来自你的数据库,你可以随心所欲地做到这一点。

.StartsWith("whatever") Linq扩展方法是一个很好的比较,而不是使用.Substring(0,7) == "whatever"

public static void Main()
{
    var words = new List<WordForm>();
            words.Add(new WordForm { WordId = "Apple" });
    words.Add(new WordForm { WordId = "Banana" });
    words.Add(new WordForm { WordId = "Cake" });
    words.Add(new WordForm { WordId = "Date" });
    words.Add(new WordForm { WordId = "Egg" });

    var filterChars = new string[] { "C", "D" };
    var filtered = GetStartingWith(filterChars, words);

    foreach (var item in filtered)
    {
       Console.WriteLine(item.WordId);
    }

}

public static List<WordForm> GetStartingWith(string[] startingLetters, List<WordForm> collection)
{
    var returnList = new List<WordForm>();

    foreach (var wordForm in collection)
    {
        foreach (var startingLetter in startingLetters)
        {
            if (wordForm.WordId.StartsWith(startingLetter))
            {
                returnList.Add(wordForm);
            }
        }
    }

    return returnList;
}

public class WordForm
{
    public string WordId { get; set; }
    //... Plus all your other properties on WordForm...
}

这会让我回头

  

控制台中的“蛋糕”和“日期”。

以上内容:

给方法一个字母列表进行检查:在这种情况下A,B,C,D,E;以及要检入的列表(您的List<WordForm>集合)

然后循环遍历WordForm对象并检查它是否以您给出的任何startingLetters开头。

如果匹配起始字母,例如"Cake".StartsWith("C")(Cake以“C”开头),然后将其添加到列表中,然后将其与过滤后的对象一起返回。