【问题标题】:LINQ TO SQL Replace methodLINQ TO SQL 替换方法
【发布时间】:2018-03-08 15:02:01
【问题描述】:

我有代码,它工作正常。

 using (var dbContext = new UnitOfWorkFactory(sqlConnection).Create())
 {
        var result = dbContext.Repository<SomeTable>()
            .Get()
            .AsNoTracking()
            .Where(r => r.Id == 1)
            .Select(item => new
            {
                TableId = item.TableId,
                OriginalTableName = item.TableName.Replace("$", "_")
            })
            .SingleOrDefault(); 

当我尝试在单独的私有方法中替换逻辑时,我得到了异常。我知道主要原因是 LINQ to SQL 提供程序无法将 clr 方法转换为 SQL。

...
.Select(item => new
 {
   TableId = item.TableId,
   OriginalTableName = SubQueryReplace(item.TableName)
 })
...

实际上我想我必须使用表达式树,但无法解决我必须如何编写它。当我尝试从 SubQueryReplace 方法返回 Expression&lt;Func&lt;string&gt;&gt; 时,CLR 编译器不满意,但是当我尝试执行类似

的操作时
private Expression<Func<string, string>>SubQueryReplace(string fieldValue)
{
   Expression<Func<string, string>> exp = (tableName) => tableName.Replace("D", "_");`
   return exp
}

...
.Select(item => new
 {
   TableId = item.TableId,
   OriginalTableName = SubQueryReplace.Compile.Invoke(item.TableName)
 })
...

LINQ to Sql 不明白我想从中得到什么。

所以你可以看到我很困惑。请帮助解决这个语法任务。

【问题讨论】:

  • 为什么要把这个逻辑放到单独的函数中?
  • 因为有很多重复的功能。许多不同的方法使用相同的逻辑。我真的认为我必须以单独的方法移动它,或者实现规范模式并在规范中移动所有重复的逻辑
  • 你能不能也提一下这个例外?
  • Somethink 像 linq to sql 不支持 SubQueryReplace 方法
  • @AllmanTool Replace 方法可以在 entityframework 6.2 版本中转换为 sql

标签: c# linq linq-to-sql expression-trees


【解决方案1】:

使用 LinqKit,并编写:

...
.AsExpandable()
.Select(item => new
 {
   TableId = item.TableId,
   OriginalTableName = SubQueryReplace(item.TableName).Expand()
 })
...

【讨论】:

    【解决方案2】:

    您的问题是 IQueryable 不能使用任何本地函数并且不能将所有标准 LINQ 方法转换为 SQL,如supported and unsupported LINQ methods 中所述,我说得对吗?

    我会选择AsEnumerable。 AsEnumerable 会将输入带到本地内存,以便您可以调用任何您想要的本地函数。

    由于您的查询结果似乎只有一个元素,因此如果您在将完整的 tableName 转换为 OriginalTableName 之前将其传输到本地内存,这不是问题

    var result = dbContext.Repository<SomeTable>()
        ...
        .Where(someTableElement => someTableElement.Id == 1)
        .Select(tableItem => new
        {
            TableId = tableItem.TableId,
            TableName = tableIem.TableName,
        })
        .AsEnumerable()
    
        // from here, all elements (expected to be only one) are in local memory
        // so you can call:
        .Select(localItem => new
        {
            TableId = localItem.TableId,
            OriginalTableName = localItem.TableName.Replace("$", "_")
        })
        .SingleOrDefault(); 
    

    使用AsEnumerable 时要小心。尽量不要将大量您不会使用的数据传输到本地内存。所以尽量在 AsQueryable 时执行 Join/Where/Select。仅当您将数据限制在您真正计划使用的范围内时,才将其移动到本地内存

    【讨论】:

    • 感谢您的关注,但我提出问题的主要原因是以更方便的方式使用 Iqueryble。一般 linq 替换函数在 Iqueryble 中工作,在 Iqueryble 之外的私有方法中不起作用
    猜你喜欢
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多