大家剛接觸LINQ的時候或許都會和我一樣,整的一句話:那是相當滴激動!
左一句lambada右一句lambada,那簡直是程序員的藝術。
寫着寫着,我靠,問題來了,LINQ TO SQL中的like怎么實現?
有人說:我用SqlMethods,例:
var query = from c in LQDC.Customers
where SqlMethods.Like(c.City, "L_n%")
select c;
可是問題依舊,假如我用的是通用字段模糊查詢呢?例如我一個下拉列表里有所有的字段名,那么客戶選擇下拉列表是隨機的,那我不是要
switch(item){
case "city":
...
break;
case "name":
...
break;
}
有幾個字段就寫幾個case,我靠,瘋了。
又有人說了,那用反射。。我靠,人家用LINQ的目的是什么,提高開發效率,減少開發時間,而且LINQ的反射也不是一般人隨便就寫得出來的。
哎,沒辦法,查了很多資料,解決方法如下:
(1)通過直接執行查詢語句,這也是LINQ的老爸估計想到目前LINQ不完善而專門留下來的絕招:
LinQDataContext LQDC = new LinQDataContext();
LQDC.ExecuteQuery("select * from table where item like %ak47%");
這里順帶提醒大家%ak47%是會丟失數據庫索引的,而ak47%則不會,要怎么解決想想博客,這里就不扯那么遠啦。
有人講啦,我靠又回到土辦法啦,我講:你NND,誰叫它不完善呢?
(2)調用存儲過程。
寫好一個存儲過程,例如名稱叫p_LikeSelect;
ALTER PROCEDURE [dbo].[p_LikeSelect] @tablename nvarchar(255), @columnname nvarchar(255),
@value nvarchar(255) AS BEGIN set nocount on; declare @sqlcommand nvarchar(max); set @sqlcommand = 'select * from '+@tablename+' where.....(后面自己寫啦)
exec sp_executesql @sqlcommand ; END
但是問題又來啦,當你把這個存儲過程通過服務器資源管理器拖進dbml窗口以后,看看里面的返回值,我靠,不管你是左拖還是右拖上拖下拖,反正拖死你還是返回int,NND,你不能智能點嗎?造成的原因是存儲過程結尾用了exec,但是你要實現動態拼接字符串必須用exec,懂的朋友都知道(所以如果你結尾是select...什么的,它才可以識別出一個ISingleResult<T>或IMultipleResults<T>的返回類型,然后通過屬性修改器把它返回值手動修改成IQueryable<Customers>這樣才能最終被使用和保存)。
沒辦法,那只好手動強行修改dbml下的linq.designer.cs文件,打開找到
[Function(Name="dbo.p_LikeSelect")] public int p_TYSelect([Parameter(DbType="NVarChar(255)")] string tablename, [Parameter(DbType="NVarChar(255)")] string @columnname.......) { IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), tablename, diskname); return ((int)(result.ReturnValue)); }
把里面所有類型int全部修改成IQueryable<Customers>如下:
[Function(Name="dbo.p_LikeSelect")] public IQueryable<Customers> p_TYSelect([Parameter(DbType="NVarChar(255)")] string tablename, [Parameter(DbType="NVarChar(255)")] string @columnname.......) { IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), tablename, diskname); return ((IQueryable<Customers>)(result.ReturnValue)); }
嘔,擦了一把汗,可是,神種是喜歡作弄人,當你再次修改dbml文件的時候,所有代碼又被重新覆蓋了,所以目前我最討厭LINQ的另外一個原因就在此了。真想罵它!這就意味着只要你系統沒有完成你就別想該dbml文件。。。費。
(3)我發怒了,要使用暴力了!!
從網上下載了DynamicLibrary.cs或叫Dynamic.cs的,大小越70-80KB左右,
using System.Linq.Dynamic; //using一下。
ok,開始有搞頭啦。舉個例子,所有字段item和查詢的值value都可以動態啦,下面我截取了一段我項目中的使用(寫得不好不要打我呀)
if (selectnum == 0) { IQ = LQDC.Transport_Inner; } else { switch (type) { case "精確": if (itemtype == "tree" || itemtype == "specialtext") { IQ = LQDC.Transport_Inner.Where(item + "=@0", value); } else if (itemtype == "bit") { IQ = LQDC.Transport_Inner.Where(item + "=@0", Convert.ToBoolean(value)); } else if (itemtype == "text") { if (!value.Trim().Equals("")) { IQ = LQDC.Transport_Inner.Where(item + "=@0", double.Parse(value)); } else { IQ = LQDC.Transport_Inner.Where(item + "=null"); } } else { IQ = LQDC.Transport_Inner.Where(item + ">=@0 and " + item + "<@1", date1.Date, date2.Date); } break; case "模糊": StringBuilder sb = new StringBuilder(); IQ = LQDC.Transport_Inner.Where(@"BackNum.Contains(""000147"")"); break; } }
動態的內容都在“精確”里面的Where里,大家應該很容易看懂(還包括動態時間的比較)
精華在最后“模糊”那,你可以通過查詢LINQ生成的SQL語句得到:
SELECT * FROM [dbo].[Transport_Inner] AS [t0]
WHERE [t0].[BackNum] LIKE @p0
類似於匹配以000147開頭的或是中間的或是結尾的,類似%000147%嘿嘿。
我靠,太牛了。真的感動了一次。神呀,你終於拯救了我!!!
終於搞定了,呼呼,,,用了兩年LINQ一直捆繞着我的LIKE終於搞死它了。
好了,還剩下一個大問題,假如我想用到sql中的new id()這個隨機查詢一個記錄,怎么辦?LINQ中也沒有呀,同樣得用到Dynamic.cs。
好了使用起來也很方便,如下,查詢ID>5並小於100的隨即5條記錄。我靠,牛:
var query = LQDC.Transport_Inner.Where("ID>@0 and ID<@1", 5, 100).Select("new(id)").Take(5)
當然,這只能返回IQueryable而非IQueryable<T>
那么關於LINQ的NEW ID()還有兩個方法,這些網上資料就很多了,而且也很好用,那我就不貼出來了,大家可以自己搜。
象我這么懶的人,居然寫了這么多,實在是因為一時激動,希望對學習或使用LINQ的人有所幫助,也希望LINQ能在.NET4.0中發揮更出色的作用!!!LINQ,加油!
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/alamiye010/archive/2009/03/02/3950597.aspx