【问题标题】:Regex Replace to assist Orderby in LINQ正则表达式替换以协助 LINQ 中的 Orderby
【发布时间】:2008-12-22 17:47:34
【问题描述】:

我正在使用 LINQ to SQL 从数据库中提取记录,按字符串字段对它们进行排序,然后对它们执行一些其他工作。不幸的是,我排序的名称字段来自数据库,如下所示

Name
ADAPT1
ADAPT10
ADAPT11
...
ADAPT2
ADAPT3

我想按数字顺序对名称字段进行排序。现在我正在使用 Regex 对象将“ADAPT1”替换为“ADAPT01”等。然后我使用另一个 LINQ 查询再次对记录进行排序。我的代码看起来像

    var adaptationsUnsorted = from aun in dbContext.Adaptations
                              where aun.EventID == iep.EventID
                              select new Adaptation
                              {
                                  StudentID = aun.StudentID,
                                  EventID = aun.EventID,
                                  Name = Regex.Replace(aun.Name,
                                     @"ADAPT([0-9])$", @"ADAPT0$1"),
                                  Value = aun.Value
                              };

    var adaptationsSorted = from ast in adaptationsUnsorted
                            orderby ast.Name
                            select ast;

    foreach(Adaptation adaptation in adaptationsSorted)
    {
        // do real work
    }

我遇到的问题是foreach循环抛出异常

System.NotSupportedException was unhandled
  Message="Method 'System.String Replace(System.String, System.String,
    System.String)' has no supported translation to SQL."
  Source="System.Data.Linq"

我还想知道是否有一种更简洁的方法可以仅使用一个 LINQ 查询来完成此操作。任何建议将不胜感激。

【问题讨论】:

  • 抛出异常是因为 Linq to Sql 试图将您的查询解析为表达式树,并且无法为您的正则表达式替换确定等效的 sql 命令,但似乎没有。跨度>

标签: c# regex linq linq-to-sql


【解决方案1】:

通过枚举查询(调用 ToList)强制元素水合。从那时起,您的操作将针对内存中的对象,并且这些操作不会被转换为 SQL。

List<Adaptation> result =
  dbContext.Adaptation
  .Where(aun => aun.EventID = iep.EventID)
  .ToList();

result.ForEach(aun =>
  aun.Name = Regex.Replace(aun.Name,
    @"ADAPT([0-9])$", @"ADAPT0$1")
);
result = result.OrderBy(aun => aun.Name).ToList();

【讨论】:

  • 我可能会创建一个已编译的静态 Regex 实例,而不是每次都使用 Regex.Replace。我不确定是否有任何优化,但如果没有,你会在一个循环中做很多事情......
【解决方案2】:

用您的逻辑实现IComparer&lt;string&gt;:

var adaptationsUnsorted = from aun in dbContext.Adaptations
                          where aun.EventID == iep.EventID
                          select new Adaptation
                          {
                              StudentID = aun.StudentID,
                              EventID = aun.EventID,
                              Name = aun.Name,
                              Value = aun.Value
                          };

var adaptationsSorted = adaptationsUnsorted.ToList<Adaptation>().OrderBy(a => a.Name, new AdaptationComparer ());

foreach (Adaptation adaptation in adaptationsSorted)
{
    // do real work
}

public class AdaptationComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        string x1 = Regex.Replace(x, @"ADAPT([0-9])$", @"ADAPT0$1");
        string y1 = Regex.Replace(y, @"ADAPT([0-9])$", @"ADAPT0$1");
        return Comparer<string>.Default.Compare(x1, y1);
    }
}

我没有测试这段代码,但它应该可以完成这项工作。

【讨论】:

    【解决方案3】:

    我想知道您是否可以将计算+持久+索引字段添加到数据库中,为您执行此操作。编写一个以整数形式获取值的 UDF(仅使用字符串值)将是相当简单的,但是您可以在数据库中对该列进行排序。这将允许您有效地使用Skip 和Take,而不是不断将所有数据提取到 .NET 代码(根本无法扩展)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-27
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多