我有代碼,它工作正常。
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不明白我想從中得到什麼。
所以你可以看到我很困惑。請幫助解決這個語法任務。
使用LinqKit,寫道:
...
.AsExpandable()
.Select(item => new
{
TableId = item.TableId,
OriginalTableName = SubQueryReplace(item.TableName).Expand()
})
...
我是對的,你的問題是IQueryable不能使用任何本地函數,並且不能將所有標準LINQ方法轉換為SQL,如支持和不支持的LINQ方法中所述 ?
我會去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。只有當您將數據限制為您真正計劃使用的數據時,才將其移至本地內存