而是在 SSMS 敲 SQL 的時候
當時在 try 舊 DB 資料轉移新 DB 的整合的方法
說時遲那時快
這鬼才 DB 的 account 欄位的資料 竟然有在重複的 但是 key 不同
雖然登入是靠 SSO 的方式 但是 account 相同應該還是無法辨識才對
除了那些真正相同的 account 之外 忽然發現 大小寫不同 但是字串相同 也會被判斷成相同
估狗了一下才發現 原來 MSSQL 預設是沒在管大小寫的
跟啥 定序 之類的鬼東西有關
解法自然也有
1.直接改那個 定序 的設定
2.加上關鍵字 COLLATE Chinese_Taiwan_Stroke_CS_AS
參考
這種 MSSQL 才有的專屬天使
LINQ to Entities 應該絕對是會無視它的
立馬玩一下 果真如此
走訪 估狗 跟 stackoverflow 之後 解法約有二
1. .ToList() 之後再玩一次 因為這時候後就是 C# 物件 就認得大小寫
但是資料多的話肯定是 GG
2. 用之前的 T - SQL 方法 有很多鬼法子可以讓 LINQ to Entities 也吃 T - SQL
但是就跟 ORM 精神說掰掰
目前的選擇是 2 因為 1 讓人覺得實在多此一舉
但是要搞這種家醜不得外揚的東東
通常都會包成一個方法
有朝一日科技進步 或者 牛人出世 之際 再來改做法
雖然理想上我想要包成這種感覺
var q = db.user.UpperOrLowerCaseWhere(x => x.account == "amy");
讓人有種還是 LINQ 的錯覺
但是實際上有許多難點
1. 可能要反射來反射去 我才有辦法抓到 "account" 這個欄位名稱
2. 浪打返回布林 那我也無法抓到 "amy" -.-
3. 最後還是靠 T - SQL 作亂 如果在這行後面在加其他 LINQ 方法 肯定也是 GG
最後選擇擴充 IQueryable<T> 用法如下
var q = db.user.AsQueryable().UpperOrLowerCaseEquals(db, "account", "amy");
Where() 會轉成 IQueryable<T> 所以不必加 AsQueryable()
var q = db.user .Where(x => x.email.Length > 0) .UpperOrLowerCaseEquals(db, "account", "amy");
Extension 大概長這樣
public static class IQueryableExtension { public static IEnumerable<TEntity> UpperOrLowerCaseEquals<TEntity>( this IQueryable<TEntity> query, DbContext db, string columnName, string keyword ) where TEntity : class { string sql = query.ToString(); IObjectContextAdapter adapter = db as IObjectContextAdapter; ObjectContext objectContext = adapter.ObjectContext; var q = objectContext.ExecuteStoreQuery<TEntity>( string.Format(@" SELECT * FROM ( {0} ) AS [table] WHERE [{1}] COLLATE Chinese_Taiwan_Stroke_CS_AS = @keyword ", sql, columnName ), new SqlParameter("@keyword", keyword) ); return q.ToList(); } }
命名為 UpperOrLowerCaseEquals 而非 UpperOrLowerCaseWhere
則是限制只用在相等比較
WHERE 要搞定的東東或許太複雜 ˊ_>ˋ
最後...牛人快出世吧
沒有留言:
張貼留言