LINQ TO SQL替换方法

时间:2018-03-06 06:58:51

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

我的代码,它运作正常。

 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<Func<string>>时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并不了解我的需求。

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

2 个答案:

答案 0 :(得分:1)

使用LinqKit,并写:

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

答案 1 :(得分:0)

我是否正确,您的问题是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。只有当您将数据限制在您真正计划使用的内容时,才将其移至本地内存