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

简介:
[索引页]
[源码下载]


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


作者: webabcd


介绍
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 
        { 
Random _random =  new Random() Random _random =  new Random(); 
void Page_Load() 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 
        { 
void Page_Load() 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 
        { 
void Page_Load() 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 
        { 
void Page_Load() void Page_Load(object sender, EventArgs e) 
                { 
                        Demo1(); 
                        Demo2(); 

                        // 支持 Single() 扩展方法了,之前的版本不支持 
                } 

void Demo1() 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 />"); 
                } 

void Demo2() 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> 
static  string GetFullName() 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> 
 
 



     本文转自webabcd 51CTO博客,原文链接:http://blog.51cto.com/webabcd/341378 ,如需转载请自行联系原作者

相关文章
|
12天前
|
人工智能 开发框架 Devops
.NET技术概览:** 本文探讨了.NET的核心特性,包括多语言支持、Common Language Runtime、丰富的类库和跨平台能力,强调其在企业级、Web、移动及游戏开发中的应用。
【7月更文挑战第4天】.NET技术概览:** 本文探讨了.NET的核心特性,包括多语言支持、Common Language Runtime、丰富的类库和跨平台能力,强调其在企业级、Web、移动及游戏开发中的应用。此外,讨论了.NET如何通过性能优化、DevOps集成、AI与ML支持以及开源策略应对未来挑战,为开发者提供强大工具,共创软件开发新篇章。
20 3
|
1月前
|
存储 编译器
【.NET Core】特性(Attribute)详解
【.NET Core】特性(Attribute)详解
34 2
|
2月前
|
机器学习/深度学习 存储 开发工具
【专栏】解读 .NET 技术的先进特性
【4月更文挑战第29天】.NET 技术推动各行业软件开发创新,提供高效开发环境(如Visual Studio)和跨平台能力(.NET Core),支持多语言和函数式编程。其生态系统繁荣,NuGet包含大量开源库。同时,.NET整合云服务(Azure)和机器学习(ML.NET),强化应用扩展性和智能处理,巩固其在现代开发中的关键角色。
|
2月前
|
XML 开发框架 .NET
C# .NET面试系列八:ADO.NET、XML、HTTP、AJAX、WebService
## 第二部分:ADO.NET、XML、HTTP、AJAX、WebService #### 1. .NET 和 C# 有什么区别? .NET(通用语言运行时): ```c# 定义:.NET 是一个软件开发框架,提供了一个通用的运行时环境,用于在不同的编程语言中执行代码。 作用:它为多语言支持提供了一个统一的平台,允许不同的语言共享类库和其他资源。.NET 包括 Common Language Runtime (CLR)、基础类库(BCL)和其他工具。 ``` C#(C Sharp): ```c# 定义: C# 是一种由微软设计的面向对象的编程语言,专门为.NET 平台开发而创建。 作
219 2
|
2月前
|
开发框架 .NET Java
ASP.NET Core高级编程--C#基本特性(一)
本文章简略介绍C#的部分特性
|
2月前
|
SQL 开发框架 .NET
ASP.NET WEB+EntityFramework数据持久化——考核练习库——1、用户管理系统(考点:查询列表、增加、删除)
ASP.NET WEB+EntityFramework数据持久化——考核练习库——1、用户管理系统(考点:查询列表、增加、删除)
92 0
|
2月前
|
存储 开发框架 .NET
Asp.net就业课之Ado.net第一次课
Asp.net就业课之Ado.net第一次课
26 0
|
9月前
|
开发框架 前端开发 .NET
ASP.NET Core 核心特性学习笔记「下」
ASP.NET Core 核心特性学习笔记「下」
|
9月前
|
开发框架 前端开发 中间件
ASP.NET Core 核心特性学习笔记「上」
ASP.NET Core 核心特性学习笔记「上」
.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法
.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法
137 0