[Entity Framework與LINQ開發實戰] 資料類型為 nvarchar 或 nchar 在EF遇到的問題

[Entity Framework與LINQ開發實戰] 資料類型為 nvarchar 或 nchar 在EF遇到的問題

最近在開發一個搜尋功能時,遇到一個條件一直搜尋不到的問題。

有經驗的人看到第一句話跟這篇的標題,也許就猜到是怎麼回事了,

但由於在ORM的情況下,有時沒有仔細去看資料庫的欄位型態,

只知道物件的型態。因此遇到時還真的會愣了一下。

其實這個問題並不屬於EF的問題,但算是使用ORM技術時,需要注意的小地方吧。

 

首先我開了一個測試Table,只有簡單的兩個欄位,除了PK外,另一個是nchar(10)型態

image

資料

image

(偉榮大強烈建議我要說明:上方資料"序號"欄位後面是有空白的,只是在上方看不出來。)

接下來的部分,我用LinqPad載入包含edmx的dll來做Demo

image

請看一下上圖,在兩個搜尋條件中,得到的答案會是什麼‧

結果是

image

看到這個結果,在不知道資料庫原始欄位的型態情況下,真的會想揉揉眼睛。

 

由於 nvarchar 、varchar 與  nchar 、char的差別

在於前者是可變長度,後者是固定長度。(有n的代表支援Unicode)

因此在此例中,如果去算序號這個欄位的長度的話,算出來都會是 10 。

 

但為何在ToList()跟沒有的結果會有差別呢?

因為ToList()之後,對資料的搜尋就是對List集合的搜尋,

因此實際的資料是 "1111          " ,而下的條件為"1111"。所以第一個搜尋結果為False。

補充:有興趣的可以看一下這篇 SET ANSI_PADDING (Transact-SQL)

 

而第二條語法則是經由EF的Provider產出SQL語法在資料庫做查詢,

而資料庫對於這樣的搜尋有特別處理,請看下圖:

image

上圖前兩條語法,不管是"1111"或"1111     "都搜尋的到。

而"     1111"則搜尋不到。

我想SQL在搜尋時,會將搜尋條件補足或截斷後面的空白直到兩者相同長度,因此前兩條才會為True吧。

(關於上面這句話我沒有搜尋到官方文件,因此只是我的臆測。如果有的話麻煩分享一下,謝謝。)

 

算是一個小眉角,如果沒仔細看資料庫很容易忽略掉,

因此享受ORM的優點同時,資料庫的基本觀念還是不能少的~