2010年4月18日 星期日

EF 4: 執行 Sql script

以往上 EF 3.5 時,ObjectContext 只能執行 eintity sql。

在 EF 4.0 時,可以直接執行 T-Sql 語法了。如下範例

   1: static void Main(string[] args)
   2: {
   3:   string sql = "select name from sys.objects ";
   4:   using (ObjectContext context = new ObjectContext("name=db"))
   5:   {
   6:     var names =  context.ExecuteStoreQuery<string>(sql);
   7:     foreach (var name in names)
   8:       Console.WriteLine(name);
   9:   }
  10: }

優點

如果自己已經知道有更好的 sql script 下法,又不想寫成 stored procedure 時,就可以使用這樣的寫法。

缺點

以往認為 Entity framework 或 Linq to Sql 是沒有 sql injection 的問題。這樣一來方便之門一開,牛鬼蛇神又可以暗渡陳倉了。

在上例中,如果要取得 string sql = "select name, database_id from sys.databases" 的結果時,就無法以單一 string 得到回傳值。程式必須增加一個新的類別,以得到回傳值。如下例。

   1: class Program
   2:   {
   3:     static void Main(string[] args)
   4:     {
   5:       string sql = "select name, database_id from sys.databases";
   6:       using (ObjectContext context = new ObjectContext("name=db"))
   7:       {
   8:         var names = context.ExecuteStoreQuery<Result>(sql);
   9:         foreach (Result r in names)
  10:           Console.WriteLine("{0}:{1}",r.Database_Id, r.Name);
  11:       }
  12:     }
  13:  
  14:     class Result
  15:     {
  16:       public int Database_Id { get; set; }
  17:       public string Name { get; set; }
  18:     }
  19:   }

缺點

select 不同數目的欄位,就必須宣告不同的類別(如 Result)以獲得回傳值。果然不是很方便。L2S 就有這樣的工具,那 Entity framework 有沒有呢? EF 4.0 就實作這樣的工具了。

首先,當然需要建立 stored procedure 了

   1: create proc usp_Sample1
   2: as 
   3:     select name, database_id from sys.databases

再來,在 entity data model designer 上按右鍵,執行 Update model from database,並選取剛剛建立的 usp_Sample1

image

打開 Model Browser,在 Model1.edmx/Store/Stored Procedures 下選到剛剛的 usp_Sample1後,按右鍵執行 Add Function Import功能

image

由於我們的回傳值是多欄位的型態,當然是 Complex。選擇 Complex 了,再按 Get Column Information鍵

image

接著按 Create New Complex Type鍵,精靈會幫我們產生符合需求的類別。同時,我們也可以修改類別的名稱。由於是 demo,此時我們不修改。完成後按 ok 鍵.

image

最後修改程式如下。

   1: static void Main(string[] args)
   2: {
   3:   using (var context = new DbEntities("name=MSPetShop4Entities"))
   4:   {
   5:     var names = context.ExecuteFunction<usp_Sample1_Result>("usp_Sample1");
   6:     foreach (usp_Sample1_Result r in names)
   7:       Console.WriteLine("{0}:{1}",r.database_id, r.name);
   8:   }
   9: }

優點

這樣一來,程式少寫了一點,是比較愉快的事。但事實上 code 的行數並沒有減少,只是改使用了 Entity Data Model 所產生的程式碼。要選哪一種呢?當然選後者,因為後者出錯的機會比較少,交給新人時,就更有把握了。

 

結論

在 Entity Framework 3.5 時,常常會拿來與 Linq To Sql (L2S) 作一番功能比較。到了 Entity Framework 4.0 時,無論在 framework 本身或工具上,都能完整地涵蓋原來  L2S的功能。相信下一版的 Visual Studio 出現時,大概 L2S 會被正式地被 deprecate 了.

沒有留言:

Share with Facebook