1. 程式人生 > >Linq中欄位資料型別轉換問題(Linq to entity,LINQ to Entities 不識別方法"System.String ToString()"問題解決)

Linq中欄位資料型別轉換問題(Linq to entity,LINQ to Entities 不識別方法"System.String ToString()"問題解決)

1、在工作中碰到這樣一個問題:

使用linq時,需要查詢兩個表,在這兩張表中關聯欄位分別是int,和varchar()也就是string,在linq中對這兩個欄位進行關聯,

如果強制型別轉換兩個不同型別的欄位,就會報響應的擴充套件方法無法自動推斷引數型別的問題(比如:我用的是groupjoin擴充套件方法),

如果進行了常規的型別轉換,比如將int欄位對應的轉換為string(ToString方法),這時編譯的時候不會有問題了。

但是在執行的時候會報如下錯誤:

LINQ to Entities 不識別方法"System.String ToString()",因此該方法無法轉換為儲存表示式.

2、解決方法:

使用System.Data.Objects.SqlClient.SqlFunctions.StringConvert()對相應的欄位進行轉換,結果可以了。

比如:

我有問題的Linq是下面這個:

var borrowLeftOutJoinLog =
                query.GroupJoin(
                    groupRtnToolByID,
                    c => c.ID.ToString(),
                    d => d.BizID
, (g, f) => new { Item = g, Detail = f })
                    .SelectMany(detail => detail.Detail.DefaultIfEmpty(), (a, b) => new { a.Item, RtnSum = (decimal?)b.RtnSum })
                    .Where(a => (a.RtnSum ?? 0) < a.Item.TBor_Qty)
                    .Select(a => a.Item);

注意:上面的ID和BizID是有關聯的,但是在兩個表中分別被設計成了int,string,所以這裡對ID進行了ToString的轉換,結果出現了上面提示的錯誤。

運用解決方法後的語句如下:

var borrowLeftOutJoinLog =
                query.GroupJoin(
                    groupRtnToolByID,
                    c => System.Data.Objects.SqlClient.SqlFunctions.StringConvert((double)c.ID),
                    d => d.BizID

, (g, f) => new { Item = g, Detail = f })
                    .SelectMany(detail => detail.Detail.DefaultIfEmpty(), (a, b) => new { a.Item, RtnSum = (decimal?)b.RtnSum })
                    .Where(a => (a.RtnSum ?? 0) < a.Item.TBor_Qty)
                    .Select(a => a.Item);

3、後感:

遇到這個問題後,自己嘗試瞭解決,可是都行不通,於是轉而求助網路(感謝這個時代吧!!!),

也看到了幾篇關於這個的解決方法,其中就包括ToString方法,而且還言之鑿鑿,再不就是說一些框架,底層問題,

難道我為了這個芝麻大點的事,也要去自己重寫,去實現很多內容嗎??

如果是,只能說我選錯了技術,它還不成熟。

可是,結果不是這樣的,Linq出來已經很久了,它包含的內容也是很多,不應該是這樣的,所以我繼續找

在這裡我找到了:

這句介紹了問題的原因:StingyJack, the problem is with the ELINQ (linq 2 entities), because it translates your code to SQL, and when it comes to an inner ToString request, it doesn't know how to translate 'ToString' to SQL. Unlike with linq 2 objects, when there is no translation, and everything is CLR lambdas, then it's performed directly on the requested objects;

下面這個給了具體的解決方法:

With EF v4 you can useSqlFunctions.StringConvert. There is no overload for int so you need to cast to a double or a decimal. Your code ends up looking like this:

var items =from c in contacts
        selectnewListItem{Value=SqlFunctions.StringConvert((double)c.ContactId),Text= c.Name};
99
Why on earth wouldn't they include an overload for int?– Jeremy Coenen
1
What does theSqlFunctions.StringConvertpart of your query look like? From the error it sounds like you are passing aNullable<double>(double?) instead of adouble. Try callingGetValueOrDefault()before you pass it in.– Brian Cauthon
5
@Nestor This doesn't work for SQL Compact. Found that out the hard way.– Austin
3
To avoid the whitespaces before the result, you should useSqlFunctions.StringConvert((double)c.ContactId).Trim()– Kim Tranjan
1
Seems not to work for SQLite using System.Data.SQLite The Methode 'System.String StringConvert(System.Nullable`1[System.Double])' in Typw 'System.Data.Objects.SqlClient.SqlFunctions' kann nicht in einen Speicherausdruck für 'LINQ to Entities' übersetzt werden. (cannot be translated into "LINQ to Entities")– OneWorld
show4more comments

所以,我覺得回答別人問題時要慎重,要針對別人給出的條件自己去試驗,不能簡單憑經驗,不能說空話,更不能想當然。

給出結果要直接(當然如果要是一語中的,切中要害,那當然不用直接給出,可是我沒有這樣的功力,起碼在linq上沒有)。