程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 精進不休.NET 4.0 (7) - ADO.NET Entity Framework 4.0新特性

精進不休.NET 4.0 (7) - ADO.NET Entity Framework 4.0新特性

編輯:關於.NET

介紹

ADO.NET Entity Framework 4.0 的新增功能

* 對外鍵的支持,即把外鍵當做實體的一個屬性來處理

* 對復雜類型的支持,即實體屬性可以是一個復雜類型

* 將多個表映射到一個概念實體,將一個表拆為多個概念實體

* 增強了 LINQ to Entities

* 新增了對 POCO(Plain Old CLR Object)的支持,即 Model 代碼中不會有任何關於持久化的代碼

* 其他新特性

示例

1、外鍵 的 Demo

EntityFramework/ForeignKeys/Demo.aspx.cs

代碼

/*
  * ADO.NET Entity Framework 4.0 - 新增了對外鍵的支持,即把外鍵當做實體的一個屬性來處理
  */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DataAccess.EntityFramework.ForeignKeys
{
     public partial class Demo : System.Web.UI.Page
     {
         private Random _random = new Random();
         protected void Page_Load(object sender, EventArgs e)
         {
             // 在一個已存在的產品類別下新建一個產品(通過外鍵值)
             using (var ctx = new ForeignKeysEntities())
             {
                 Product p = new Product
                 {
                     Name = "webabcd test" + _random.Next().ToString(),
                     ProductNumber = _random.Next().ToString(),
                     StandardCost = 1,
                     ListPrice = 1,
                     SellStartDate = DateTime.Now,
                     rowguid = Guid.NewGuid(),
                     ModifiedDate = DateTime.Now,
                     ProductCategoryID = 18
                 };
                 // 這裡需要手工 Add 這個新的 Product,然後再調用 SaveChanges()
                 ctx.Products.AddObject(p);
                 Response.Write(ctx.SaveChanges());
             }
             Response.Write("<br /><br />");
             // 在一個已存在的產品類別下新建一個產品(通過外鍵對象)
             using (var ctx = new ForeignKeysEntities())
             {
                 Product p = new Product
                 {
                     Name = "webabcd test" + _random.Next().ToString(),
                     ProductNumber = _random.Next().ToString(),
                     StandardCost = 1,
                     ListPrice = 1,
                     SellStartDate = DateTime.Now,
                     rowguid = Guid.NewGuid(),
                     ModifiedDate = DateTime.Now,
                     ProductCategory = ctx.ProductCategories.Single(c => c.ProductCategoryID  == 18)
                 };

                 // 這裡直接調用 SaveChanges() 即可,而不用再手工地 Add 這個新的 Product
                 // 因為與這個新的 Product 關聯的那個已存在的 ProductCategory 會自動地 Add 這個 新的 Product
                 Response.Write(ctx.SaveChanges());
             }
         }
     }
}

2、復雜類型的 Demo

EntityFramework/ComplexType/Demo.aspx.cs

代碼

/*
  * ADO.NET Entity Framework 4.0 - 新增了對復雜類型的支持,即實體屬性可以是一個復雜類型
  * 1、在 EDM 設計器中的實體上,點擊右鍵,在“Add”選項中可以新建一個復雜類型
  * 2、在 EDM 設計器中的實體上,選中多個屬性後,點擊右鍵,選擇“Refactor into New Complex Type”可以合並多個屬 性為一個復雜類型
  * 3、在 EDM 設計器中的“Mapping Details”窗口或“Model Broswer”窗口裡,可以對復雜類型做編輯
  *
  * ADO.NET Entity Framework 4.0 - 對存儲過程的支持有了明顯的增強
  * 表現為:可以將存儲過程的返回值映射到一個自定義的復雜類型上,當然,這個復雜類型也可以根據儲過程的返回值自動生成
  */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DataAccess.EntityFramework.ComplexType
{
     public partial class Demo : System.Web.UI.Page
     {
         protected void Page_Load(object sender, EventArgs e)
         {
             using (var ctx = new ComplexTypeEntities())
             {
                 // 這裡的 Name 類型是自定義的一個復雜類型(其有三個屬性,分別為FirstName,  MiddleName, LastName),詳見 EDM
                 Name name = ctx.Customers.First().Name;
                 Response.Write(string.Format("FirstName: {0}<br />MiddleName: {1}<br  />LastName: {2}", name.FirstName, name.MiddleName, name.LastName));
             }
             Response.Write("<br /><br />");
             using (var ctx = new ComplexTypeEntities())
             {
                 // 這裡的 MyCustomer 類型,是存儲過程 uspSelectCustomer(其概念模型為: GetCustomer()) 的返回值的映射類型
                 MyCustomer customer = ctx.GetCustomer().First();

                 Response.Write(string.Format("CustomerID: {0}<br />FirstName: {1}<br  />MiddleName: {2}<br />LastName: {3}", customer.CustomerID, customer.FirstName, customer.MiddleName,  customer.LastName));
             }
         }
     }
}

3、將一個表拆為多個概念實體的 Demo

EntityFramework/TableSplitting/Demo.aspx.cs

代碼

/*
1、將多個表映射到一個概念實體,原來就可以。在 EDM 設計器中將兩個一對一的表映射到一個實體即可
2、將一個表拆為多個概念實體,原來也行,但是要在 xml 中手工配置。現在 VS2010 中只需在 EDM 設計器中做如下設置:
     a、新建兩個實體,做好相關字段相對於原表的映射
     b、在這兩個實體間新建一個一對一的關聯
     c、雙擊這個關聯線,編輯約束,指明主表和依賴表,並設置相關的主鍵
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DataAccess.EntityFramework.TableSplitting
{
     public partial class Demo : System.Web.UI.Page
     {
         protected void Page_Load(object sender, EventArgs e)
         {
             // 將一個 ErrorLog 表映射到兩個實體上 ErrorLog 和 ErrorLogExt,詳見 EDM
             using (var ctx = new TableSplittingEntities())
             {
                 ErrorLog log = ctx.ErrorLogs.First();
                 Response.Write(log.ErrorLogID);
                 Response.Write("<br />");
                 log.ErrorLogExtReference.Load();
                 Response.Write(log.ErrorLogExt.ErrorMessage);
             }
         }
     }
}

4、LINQ to Entities 新功能的 Demo

EntityFramework/LINQ2Entities/Demo.aspx.cs

代碼

/*
  * ADO.NET Entity Framework 4.0 - 增強了 LINQ to Entities
  */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.Objects;
using System.Data.Common;
namespace DataAccess.EntityFramework.LINQ2Entities
{
     public partial class Demo : System.Web.UI.Page
     {
         protected void Page_Load(object sender, EventArgs e)
         {
             Demo1();
             Demo2();
             // 支持 Single() 擴展方法了,之前的版本不支持
         }
         private void Demo1()
         {
             // ADO.NET Entity Framework 4.0 - 新增了 System.Data.Objects.EntityFunctions 和  System.Data.Objects.SqlClient.SqlFunctions
             // 其作用相當於 Linq to Sql 中的 System.Data.Linq.SqlClient.SqlMethods
             using (var ctx = new LINQ2EntitiesEntities())
             {
                 var products =
                       from p in ctx.Products
                       where System.Data.Objects.SqlClient.SqlFunctions.DateDiff("year",  p.SellStartDate, DateTime.Now) <= 10
                       select p;

                 Response.Write((products as System.Data.Objects.ObjectQuery).ToTraceString());
                 Response.Write("<br />");
                 Response.Write("十年內銷售的產品數量為:" + products.Count());
             }
             Response.Write("<br /><br />");
             // 上面的示例如果寫成 esql 就是如下的寫法。當然這個原來就支持。
             using (var ctx = new LINQ2EntitiesEntities())
             {
                 string esql = "select value p from LINQ2EntitiesEntities.Products as p where  SqlServer.DATEDIFF('year', p.SellStartDate, SqlServer.GETDATE()) <= 10";
                 // string esql = "using SqlServer; select value p from  LINQ2EntitiesEntities.Products as p where DATEDIFF('year', p.SellStartDate, GETDATE()) <= 10";
                 ObjectQuery<Product> products = ctx.CreateQuery<Product>(esql);
                 Response.Write(products.ToTraceString());
                 Response.Write("<br />");
                 Response.Write("十年內銷售的產品數量為:" + products.Count());
             }
             Response.Write("<br /><br />");
         }
         private void Demo2()
         {
             // 使用 esql 的方式調用 sql 中的用戶自定義函數
             using (var ctx = new LINQ2EntitiesEntities())
             {
                 string esql = "select value top(1) LINQ2EntitiesModel.Store.ufnGetFullName (c.firstName, c.middleName, c.lastName) from LINQ2EntitiesEntities.Customers as c";
                 ObjectQuery<string> customers = ctx.CreateQuery<string>(esql);
                 Response.Write((customers as System.Data.Objects.ObjectQuery).ToTraceString());
                 Response.Write("<br />");
                 foreach (var customerName in customers.ToList())
                 {
                     Response.Write(customerName);
                     Response.Write("<br />");
                 }
             }
             Response.Write("<br /><br />");
             // clr 的方式調用 sql 的用戶自定義函數。具體實現見 MyClass 類
             using (var ctx = new LINQ2EntitiesEntities())
             {
                 var customers =
                     from c in ctx.Customers
                     select MyClass.GetFullName(c.FirstName, c.MiddleName, c.LastName);
                 customers = customers.Take(1);
                 Response.Write((customers as System.Data.Objects.ObjectQuery).ToTraceString());
                 Response.Write("<br />");
                 foreach (var customerName in customers.ToList())
                 {
                     Response.Write(customerName);
                     Response.Write("<br />");
                 }
             }
         }

         public static class MyClass
         {

             // System.Data.Objects.DataClasses.EdmFunction(string namespaceName, string functionName)  - 將 sql 中的指定的用戶自定義函數映射到 clr 的方法上
             //     string namespaceName - SSDL(存儲模型)的命名空間,可以在 edmx 文件中找到這個 值
             //     string functionName - sql 中的用戶自定義函數名
             [System.Data.Objects.DataClasses.EdmFunction("LINQ2EntitiesModel.Store", "ufnGetFullName")]
             /// <summary>
             /// 此方法的參數要與其所映射的 sql 用戶自定義函數的參數相匹配
             /// 此方法只可用於 linq 表達式,方法內不用做任何實現
             /// </summary>
             public static string GetFullName(string firstName, string middleName, string  lastName)
             {
                 throw new NotSupportedException("You can only call this method as part of a  LINQ expression");
             }
         }
     }
}

5、POCO 的 Demo

Demo.aspx

代碼

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Demo.aspx.cs" Inherits="POCODemo.Demo" % >
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1- transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
     <title></title>
</head>
<body>
     <form id="form1" runat="server">
     <div>
         ADO.NET Entity Framework 4.0 - 新增了對 POCO(Plain Old CLR Object)的支持,即 Model 代碼中 不會有任何關於持久化的代碼
         <ul>
             <li>1、線上有 POCO 的 T4(Text Template Transformation Toolkit)模板</li>
             <li>2、在 EDM 設計器上單擊右鍵,選擇“Add Code Generation Item”,在線上模板中選擇“ADO.NET C# POCO Entity  Generator”模板生成即可</li>
             <li>3、在 EF 中,POCO 與非 POCO 不能在一個項目中共存,因為非 POCO 的 EF 在 assembly 級別上會有如下聲明 <br />
                 using System.Data.Objects.DataClasses;<br />
                 [assembly: EdmSchemaAttribute()]<br />
                 而 POCO 不需要這個聲明,所以一個程序集內不能既有 POCO 又有非 POCO  </li>
             <li>4、具體的 POCO 代碼,詳見本例中的由 POCO 模板生成的代碼 </li>
         </ul>
     </div>
     </form>
</body>
</html>

6、其他新特性

EntityFramework/Others.aspx

代碼

<%@ Page Title="其它,一筆帶過" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
     CodeBehind="Others.aspx.cs" Inherits="DataAccess.EntityFramework.Others" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
     <p>
         1、T4 模板引擎(微軟的一個代碼生成引擎) - Text Template Transformation Toolkit
     </p>
     <p>
         2、增強了 EDM 設計器
     </p>
     <p>
         3、對 Model-First 的支持,即根據概念模型生成存儲模型和映射模型
         <ul>
             <li>在概念模型(EDM 設計器)上單擊右鍵,選擇“ Generate Database from Model”,即可生成數據庫腳本 </li>
             <li>
                 在 EDM 設計器中,與 Model-First 相關的字段屬性說明
                 <ul>
                     <li>StoreGeneratedPattern - 該字段所對應的數據庫中的列屬性(有三種:無,自增,通過計算而來)</li>
                     <li>FixedLength - FixedLength=true 對應 nchar, FixedLength=false 對應 nvarchar</li>
                     <li>Unicode - 是否是 Unicode 編碼。比如字符串如果是非 Unicode 則對應 varchar,如果是 Unicode 則對應  nvarchar</li>
                     <li>Max Length - 最大字符數。對應 varchar(n) 或 nvarchar(n) 中的 n</li>
                 </ul>
             </li>
         </ul>
     </p>
     <p>
         4、Code Only - 在 POCO 的基礎上,連 EDM 也不需要了(即不用再做概念模型,映射模型,存儲模型的配 置), 純寫代碼即可,可惜在 EF 4.0 的正式版裡這個功能被去掉了
     </p>
     <p>
         5、 改進了 SQL 語句的生成
     </p>
     <p>
         6、Lazy Loading - 支持延遲加載,相關設置 context.ContextOptions.DeferredLoadingEnabled = true;  其默認值就是 true
     </p>
     <p>
         7、Explicit Loading - 顯示加載,看下面的例子
         <ul>
             <li>加載導航屬性的方法如下(當然 Include 也可以達到同樣的效果)context.LoadProperty(category,  "Products");</li>
             <li>上面那個方法(包括 Include)不太好,因為如果實體集名稱寫錯的話 runtime 的時候是才能發現,所以為了避免寫錯可 以使用如下方法 context.LoadProperty(category, c => c.Products);</li>
         </ul>
     </p>
     <p>
         8、幾種自帶的 T4 模板的說明
         <ul>
             <li>ADO.NET EntityObject Generator - 把 edmx 文件中的內聯代碼摘出來</li>
             <li>ADO.NET POCO Entity Generator - 生成 POCO(Plain Old CLR Object) 實體,其包括每個表所映射的實體及一 個Context,POCO 中不會包含持久化相關的代碼(這個模板非內置,可以在線上模板中找到)</li>
             <li>ADO.NET Self-Tracking Entity Generator - POCO 的加強版,在 POCO 的基礎上增加了實體狀態自跟蹤的功能 </li>
         </ul>
     </p>
     <p>
         9、新建 EDM 的時候,在向導中有一個選項“pluralize or singularize generated object names”,其意 思為:生成對應的 Model 時,實體名稱自動用單數形式,實體集名稱自動用復數形式
     </p>
</asp:Content>

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved