全部設計複雜的ORM都是浮雲

好久沒有寫文章了。程序員

一直很忙,不是頗有時間整理。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();
   }
}
SQL class
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();
        }
     }
}
SQLPath class
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);
    }
    
}
SQLShop class
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=>
    {
       //取到正確數據
    });
}
demo

 

(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.不認可我上邊說的的,還執迷不悔的,就當我啥都沒說,我沒有在說你哈!

相關文章
相關標籤/搜索