好久沒有寫文章了。程序員
一直很忙,不是頗有時間整理。sql
今天主要是來吐槽下那些設計很複雜的ORM的。數據庫
項目作的越多,越以爲ORM這個東西設計的太複雜實在是沒什麼意義。後端
比較推崇Dapper這樣比較簡單,效率比較給力的是ORM。緩存
他其實什麼都沒作,只是把數據庫的字段映射到對象的字段上,我以爲就這一個功能就OK了。架構
其餘的功能對ORM來講基本上都是沒什麼用的。app
待我慢慢道來!ide
一行只寫一句話,是由於寫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.不認可我上邊說的的,還執迷不悔的,就當我啥都沒說,我沒有在說你哈!