很久沒有寫文章了。
一直很忙,不是很有時間整理。
今天主要是來吐槽下那些設計很復雜的ORM的。
項目做的越多,越覺得ORM這個東西設計的太復雜實在是沒什么意義。
比較推崇Dapper這樣比較簡單,效率比較給力的是ORM。
他其實什么都沒做,只是把數據庫的字段映射到對象的字段上,我覺得就這一個功能就OK了。
其他的功能對ORM來說基本上都是沒什么用的。
待我慢慢道來!
一行只寫一句話,是因為寫C#代碼習慣了,不是詩, 不要誤會!
你說你的ORM支持全數據庫。
啊哈,一般來說項目開始的時候數據庫就已經選好型了。
只要你不是非常二逼或傻逼,選一些非常不入流,而且能力不是很強的數據庫。
后面基本上是不會更換數據庫的。
所以,為毛要支持啊。
在通用和性能之間,有一條溝,你要么站在溝左邊,要么在溝右邊。
站中間,哈哈,掉下去了。
你說你開始的沒想到后面會有這么大的數據。
啊哈,你的架構師不給力么!
好,不是架構師的問題。
窮逼的,牛逼的MYSQL。
苦逼的,牛逼的MSSQL。
二逼的,牛逼的ORACLE。
傻逼的,牛逼的DB2。
大家一開始都是在考慮當前的需求。
並且稍稍的考慮的下未來幾年的可能,或者沒有考慮。
所以不能怪架構師,誰讓甲方剛開始只給那么點錢。
好了,時間越來越久,數據庫越來越慢。
腫么辦?
升級數據庫哈!
這不,你看還是有換數據庫的需求的吧。
啊哈,怎么說呢?
總覺得換一種數據庫就能解決問題?
世界上著名的數據庫就那幾種!
在一些特定的領域
ORACLE比MSSQL牛逼多少?
MSSQL比MYSQL牛逼多少?
牛逼不了多少的哈
沒見上邊么,每一種數據庫都有牛逼的人在用么
你覺得你的數據庫不行!
你調優了么?你優化業務了么?你還在用奔騰時代的機器來挑戰這大數據時代么?
所以,換數據庫是最最壞的打算。
而且你就算想換,現在的ORM也解決不了100%的問題啊。
數據遷徙,要專業工具!數據庫管理,要專業人員!
所以你想用一套東西來解決所有問題。
上帝尚不能造一塊自己搬不起的石頭,何況是你!
你說用了ORM,媽媽再也不用擔心的我SQL了!
啊哈,怎么吐槽你呢?
好的開發人員有四個技術基本功,知道么!
開發語言,SQL,抽象能力和自嘲!
不會任何一樣,你都不是一個好的開發。
會拿開發語言寫函數,會自定義對象,會拿語言表述一套完整的業務流程。
不錯!很不錯!
但是你還差三樣!
你起碼要會寫函數吧!知道怎么拿SQL自定義類型吧(對不起,主流數據庫都支持的哈)!會用存儲過程來表述一套完整的流程吧!
但是你差兩樣!
你說你已經寫了一套ORM可以通吃所有數據庫啦!
呵呵,不錯!來,學着星爺的腔調來一句,“其實我是一個程序員”!
哦也,你功德圓滿,隨你師父和大師兄,三師兄以及小白馬回大唐去吧!
什么!
你說不要把業務放到數據庫里面,換數據庫不方便!
騷年,從頭看看。
好,你已經看過了,但是你還是覺得放到數據庫里不放心,你還是可能換數據庫!
各種主流數據庫的表主流的字段類型基本可以通用哈。
各種主流數據庫的函數和存儲過程的調用都差不多哈。
各種主流數據庫的你有的基本大家都有哈。
只要不使用太特殊的東西,換個庫神馬的,小case啦。
你說你用了!
你說你用了ORACLE的包,Java Source!你想換!
你說你用了MSSQL的表變量,C# UDT,花了好幾千大洋裝上了R2!你想換!
你說你用了MYSQL的枚舉,對InnoDB疼愛有加!但是你想換!
.......
少年,為什么要放棄治療!
都這樣了,都滄海桑田了,你還是好好珍惜你們的感情吧。
換啥!換一種思維來解決問題吧,坑挖的越來越深的時候,就該想想是不是改往寬挖挖了!
就算非得換數據庫,你真的以為,自定義的那套別扭的語法能為你新的數據庫帶來很好的性能么?
說我了解的,只說最簡單的,而且通用的語法層面!
CTE這么好用的東西,你來,用ORM生成一條試試看。
MERGE這么好用的東西,你來,用ORM生成一條試試看。
SQL BLOCK這么好用的東西,你來,用ORM生成一條試試看。
(注:SQL BLOCK是ORACLE的叫法,MSSQL原生支持所以沒有太V587的名字)
為什么非要各種數據庫的方言上做痛苦的掙扎?
你確實練就了一身無敵的抽象能力,你確實碉堡了!
但是,呵呵,別忘了那句,“我是程序員,你叫我序員就好了”,生亦何歡死亦何苦哈,何必非要和自己過不去呢,是不!
你說你是處女座的,而且你還是個苦逼的后端程序員!
你是說你見不了后台代碼里,被SQL玷污的滿目瘡痍的開發代碼!
啊哈,SQLSHOP聽過么,把SQL全部放到外置文件里進行統一管理,所有的查詢都是按照綁定變量的方式進行。
從不拼SQL,從不把SQL寫到代碼里,復雜的業務寫成存儲過程或函數。
SQLSHOP讓你的代碼一塵不染。
SQLSHOP讓你擔心的注入問題,執行計划問題輕松解決。
SQLSHOP讓你在寫代碼的歲月里幸福的像花兒一樣。
那什么地方有SQLSHOP呢?
啊哈,剛好本仙身上帶了一包,暫給元帥嘗嘗鮮,涉及一些不太方便的代碼,請自行腦補。

public class SQL { private Dictionary<int,string> Sqls{get; set;} private Dictionary<string,object> Parameters{get; set;} public SQL(Dictionary<int,string> sqls) { if (sqls==null||sqls.Count==0)throw new NotSupportedException("sql can't empty"); this.Sqls=sqls; Parameters=new Dictionary<string,object>(); } public void AsyncExecute<T>(Action<Exception> error,Action<T> back) { //...查詢數據庫返回數據並映射到對象上 } public void Add(string pname,object value) { Parameters.Add(pname,value); } public void Clear() { Parameters.Clear(); } }

public class SQLPath:DynamicObject { private StringBuilder builder=new StringBuilder(); public override bool TryGetMember(GetMemberBinder binder, out object result) { var name = binder.Name; builder.Append('\\'); builder.Append(name); result=this; return true; } private SQLPath(){} public static dynamic RootPath { get {return new SQLPath();} } public SQL ToSQL() { return SQLShop.ReadSQL(this); } public string Path { get{ return builder.ToString(); } } }

public static class SQLShop { public static SQL ReadSQL(SQLPath sqlpath) { var path=sqlpath.Path; Dictionary<int,string> sqls=new Dictionary<int,string>(); //...按照文件組織或xml文件或者其他方式來讀取這種查詢下的全部sql,並做緩存 //...獲取全部SQL,並取出每個SQL的SQL參數的生成hash值存入到sqls的鍵種 sqls.Add(-1581397123,"SELECT USER_NAME ,USER_ID FROM T_BASE_USERS T WHERE T.USER_NAME LIKE :user_name"); sqls.Add(24307103,"SELECT USER_NAME ,USER_ID FROM T_BASE_USERS T WHERE T.USER_NAME LIKE :user_name and T.ADDRESS LIKE :address"); return new SQL(sqls); } }

void Main() { var root=SQLPath.RootPath.UserManager.UserPower.QueryUser;//用戶管理-》權限管理-》查詢用戶 var sql=(root as SQLPath).ToSQL(); sql.Add("user_name","%王"); sql.AsyncExecute<User>( ex=> { //發生異常 Console.WriteLine(ex); }, User=> { //取到正確數據 }); sql.Clear(); sql.Add("user_name","王__"); sql.Add("address","%西安%"); sql.AsyncExecute<User>( ex=> { //發生異常 Console.WriteLine(ex); }, User=> { //取到正確數據 }); }
(SQLSHOP的思想不是做一個ORM,而是做一個SQL的管理器,統一管理這些SQL,而不是凌亂的散落在各個class文件里面。)
你說我總算發現了,你對我們這些功能齊全的ORM有偏見!
啊哈,你說對了!
不過我的偏見是有理由的哈!
關系本來就是該數據庫來處理,RDBMS的第一個R就是指關系,這個關系是說數據之間的數據關系。
OO語言里面也有關系,不過是對象關系,雖然可以將數據關系按照某個原則轉換到對象上!
但是為了按照數據關系來組織數據對象總感覺不是那么美好!
NH已經不是那么火熱了!
LINQ TO SQL也已經在慢慢消失。
EF雖然活着,但只是活在很多小的項目,或者懶的開發人員那里。
要想一套很好的ORM,想想NOSQL吧!
只需要單表映射,不要再把復雜的關系組織到OO上了。
就算某天覺得關系型數據庫不給力了,想換NOSQL。
噢耶,程序里面全是單表操作,so easy!
珍愛生命,遠離復雜的ORM!
那怎么判斷一個ORM是否復雜呢?
1.全部使用對象的方式來操作數據庫。(按理說,所有的開發人員應該都是見不到物理表的,所見的只能是視圖,函數,或存儲過程)
2.由機器自動生成SQL並執行。(EF生成的SQL好么,你用一張C#的內存表關聯一張數據庫的一張表試試看,那長長的SQL,那淡淡的憂傷)
3.包含復雜的查詢語法,企圖用一套自己的語法來通吃所有數據庫。(你明白的,通吃有用?學習啥語法都不如學好SQL,數據庫就那幾種,SQL都差不多的)
4.不承認我上邊說的的,還執迷不悔的,就當我啥都沒說,我沒有在說你哈!