`

Entity Framework 学习高级篇—改善EF代码的方法

 
阅读更多

本节,我们将介绍一些改善EF代码的相关方法,如NoTracking,GetObjectByKey, Include等。

l         MergeOption.NoTracking

当我们只需要读取某些 数据而不需要删除、更新的时候,可以指定使用MergeOption.NoTracking的方式来执行只读查询(EF默认的方式是 AppendOnly)。当指定使用NoTracking来进行只读查询时,与实体相关的引用实体不会被返回,它们会被自动设置为null。因此,使用 NoTracking可以提升查询的性能。示例代码如下:

[Test ]

        public void NoTrackingTest()

        {

            using (var db = new NorthwindEntities1 ())

            {

// 针对Customers查询将使用MergeOption.NoTracking

                db.Customers.MergeOption = MergeOption .NoTracking;

                var cust = db.Customers.Where(c => c.City == "London" );

                foreach (var c in cust)

                    Console .WriteLine(c.CustomerID);

 

                // 也可以这样写

                //var cust1 = ((ObjectQuery<Customers>)cust).Execute(MergeOption.NoTracking);

 

                //Esql 写法

                //string esql = "select value c from customers as c where c.CustomerID='ALFKI'";

                //db.CreateQuery<Customers>(esql).Execute(MergeOption.NoTracking).FirstOrDefault();

 

            }

        }

 

l         GetObjectByKey/First

GetObjectByKey

在EF中,使用GetObjectByKey方法获取数据时,它首先会查询是否有缓存,如果有缓存则从缓存中返回需要的实体。如果没有则查询数据库,返回需要的实体,并添加在缓存中以便下次使用。

First: 总从数据库中提取需要的实体。

因此,我们应在合适的地方选择GetObjectByKey方法来获取数据,以减少对数据库的访问提升性能。示例代码如下:

[Test ]

        public void GetByKeyTest()

        {

            using (var db = new NorthwindEntities1 ())

            {

                // 从数据库中提取数据

                var cst = db.Customers.First(c => c.CustomerID == "ALFKI" );

                Console .WriteLine(cst.CustomerID);

 

                // 将从缓存中提取数据

                EntityKey key = new EntityKey ("NorthwindEntities1.Customers" , "CustomerID" , "ALFKI" );

                var cst1 = db.GetObjectByKey(key) as Customers ;

                Console .WriteLine(cst1.CustomerID);

 

 

           }

        }

此外,需要注意的是如果GetObjectByKey 没有获取到符合条件的数据,那么它会抛异常。为了避免此情况发生,在有可能出现异常的地方,我们应该使用 TryGetObjectByKey 方法。 TryGetObjectByKey 方法获取数据的方式和 GetObjectByKey类似,只是当没有取到符合条件的数据时, TryGetObjectByKey 会返回 null而不是抛异常。示例代码如下:

[Test ]

        public void TryGetByKeyTest()

        {

            using (var db = new NorthwindEntities1 ())

            {

 

                // 没有符合条件的数据会有异常抛出

                EntityKey key = new EntityKey ("NorthwindEntities1.Customers" , "CustomerID" , " ♂风车车.Net" );

                var cst = db.GetObjectByKey(key) as Customers ;

                Console .WriteLine(cst.CustomerID);

 

                // 没有符合条件的数据会有返回null

                EntityKey key1 = new EntityKey ("NorthwindEntities1.Customers" , "CustomerID" , " ♂风车车.Net" );

                Object cst1 = null ;

                db.TryGetObjectByKey(key1, out cst1);

                if (cst1 != null )

                    Console .WriteLine(((Customers )cst1).CustomerID);

 

            }

        }

 

l         First /FirstOrDefault

First: 当我们使用First来获取数据,如果没有符合条件的数据,那么我们的代码将会抛出异常。

FirstOrDefault: 当我们使用FirstOrDefault 来获取的数据,如果没有符合条件的数据,那么它将返回null。

显然,对于一个良好的代码,是对可以预见的异常进行处理,而不是等它自己抛出来。示例代码如下:

[Test ]

        public void FirstTest()

        {

            using (var db = new NorthwindEntities1 ())

            {

 

                // 抛异常的代码

                var cst = db.Customers.First(c => c.CustomerID == " ♂风车车.Net" );

                Console .WriteLine(cst.CustomerID);// 此处将出抛异常

               

                // 推荐的使用如下代码:

                var cst1 = db.Customers.FirstOrDefault(c => c.CustomerID == " ♂风车车.Net" );

                if (cst1 != null )

                    Console .WriteLine(cst1.CustomerID);

            }

        }

l         延迟加载/Include

EF 不支持实体的部分属性延迟加载,但它支持实体关系的延迟加载。默认情况,实体的关系是不会加载。如下代码:

[Test ]

        public void IncludeTest()

        {

            using (var db = new NorthwindEntities1 ())

            {

               var csts = db.Customers;

                foreach (var c in csts)

                {

                    Console .WriteLine(c.CustomerID);

                    foreach (var o in c.Orders)

                        Console .WriteLine("   " + o.OrderID);

                }

            }

        }

上述代码中,因为Orders没有被加载,所以在输出Orders的时候,是不会有任何输出的。

当我们需要加载某些关联的关系时,可是用Include 方法,如下代码所示:

[Test ]

        public void IncludeTest()

        {

            using (var db = new NorthwindEntities1 ())

            {

               var csts = db.Customers.Include("Orders" );

                foreach (var c in csts)

                {

                    Console .WriteLine(c.CustomerID);

                    foreach (var o in c.Orders)

                        Console .WriteLine("   " + o.OrderID);

                }

            }

        }

上述代码中,Customers关联的Orders将被加载。

l         CompiledQuery

提供对查询的编译和缓存以供重新使用。当相同的查询需要执行很多遍的时候,那么我们可以使用ComplieQuery 将查询的语句进行编译以便下次使用,这样可以免去对同一语句的多次处理,从而改善性能。

示例代码如下:

[Test ]

        public void ComplieTest()

        {

            using (var db = new NorthwindEntities1 ())

            {

                // 对查询进行编译

                var customer = CompiledQuery .Compile<NorthwindEntities1 , IQueryable <Customers >>(

                    (database) => database.Customers.Where(c => c.City == "London" ));

               

                // 执行20次相同的查询

                for (int i = 0; i < 20; i++)

                {

                    DateTime dt = System.DateTime .Now;

                    foreach (var c in customer(db))

                        Console .WriteLine(c.CustomerID);

                    Console .WriteLine(DateTime .Now.Subtract(dt).TotalMilliseconds);

                    Console .WriteLine("---------------------------------------------------" );

                }

 

             }

   }

l         存储模型视图

EF中,当执行实体查询的时候,运行时首先将实体模型转换成 ESQL视图,而 ESQL视图则是根据 msl文件来生成相应的代码。此外, ESQL视图包含了相应的查询语句。 ESQL视图被创建后将在应用程序域中进行缓存以便下次使用。这个运行时生成存储模型视图是比较耗时的过程。

为了,免去运行时生成存储模型视图,我们可以预先产生这个的存储模型视图。具体步骤如下:

首先,使用 EdmGen2来产生存储模型视图,相应的命令如下:

Edmgen2 /ViewGen cs NorthwindEntites.edmx

执行此命令后, edmgen2会在当前目录下生成一个名为 NorthwindEntites.GeneratedViews.cs 这个文件,就是我们要使用的存储模型视图文件。

将此文件添加到项目中就行,其他的代码不需要改变, EF会自动调用此视图文件。如下示例代码:

[Test ]

        public void ViewTest()

        {

            using (var db = new NorthwindEntities1 ())

            {

                var suppliers = db.Suppliers;

                foreach (var s in suppliers)

                    Console .WriteLine(s.ContactName);

            }

        }

没有使用存储模型视图的情况是:

1 passed, 0 failed, 0 skipped, took 7.09 seconds.

项目中添加了 NorthwindEntites.GeneratedViews.cs文件,执行情况是:

1 passed, 0 failed, 0 skipped, took 5.38 seconds.

可见,使用了存储模型视图的确是提高了性能。

l         冲突处理

EF中,默认情况并不会检查并发冲突。因为 EF实现的是乐观的并发模式,当有并发的冲突发生时,将会抛出 Optimistic Concurrency Exception异常。我们可以通过使用 RefreshMode 这个枚举来指定当发生冲突时如何处理。

RefreshMode 有两中枚举值:

ClientsWins: 当提交修改,更新数据库中的值。

StoreWins: 放弃修改,使用数据库中的值。

示例代码片段如下:

var db2 = new NorthwindEntities1 ();

            var customer2 = db2.Customers.FirstOrDefault(c => c.CustomerID == "2009" );

            if (customer2 != null )

            {

                customer2.ContactName = " ♂风车车.Net" ;

                customer2.City = "CD" ;

                customer2.Region = "GX" ;

            }

            try

            {

                db2.SaveChanges();

            }

            catch (OptimisticConcurrencyException ex) // 捕获到冲突,则进行相应的处理

            {

                db2.Refresh(RefreshMode .ClientWins, customer2);

                db2.SaveChanges();

            }

上述代码片段,只是说明怎么处理并发冲突,不是具体的并发。(ps:本来是准备开个线程来模拟并发的,但是始终没成功,没明白什么原因,望高人指点呢!)

分享到:
评论

相关推荐

    Z.EntityFramework.Extensions.EFCore6.13.1.zip

    《深入理解Z.EntityFramework.Extensions.EFCore6.13.1:多版本支持与BulkInsert功能》 Z.EntityFramework.Extensions是一款针对Entity Framework Core(简称EF Core)的扩展库,它提供了丰富的功能,增强了数据库...

    entityFramework源代码

    这个压缩包“entityFramework源代码”包含的是Entity Framework 6的源码,对于想要深入理解其工作原理和实现细节的开发者来说,这是一个宝贵的资源。 Entity Framework 6的主要特点包括: 1. **Code First**:这是...

    Entity Framework学习初中高级篇-博客园cnblogs.rar

    这个“Entity Framework学习初中高级篇-博客园cnblogs.rar”压缩包可能包含了一系列关于如何使用和深入理解EF的文章或教程,覆盖了从基础到进阶的各个层面。 在初学者阶段,学习Entity Framework通常从了解其基本...

    Z.EntityFramework.Extensions.EFCore.dll2.1.49EFCore破解

    替换C:\Users\xxxxx\.nuget\packages\z.entityframework.extensions.efcore\2.1.49\lib\netstandard2.0下的Z.EntityFramework.Extensions.EFCore.dll。适用于.net core的ef,解除了1个月使用的限制。

    Entity_Framework_学习.pdf

    随着学习的深入,会涉及到如何改善EF代码,包括一些高级技巧和方法,以优化代码结构和性能。在学习结束后,通常会有一个总结,强调学习的重点和实践中的注意事项。 需要指出的是,本系列课程的内容来源于风车车博客...

    Entity Framework官方中文教程

    Entity Framework(EF)是微软提供的一个对象关系映射(O/RM)框架,它简化了.NET开发人员访问数据库的代码编写,无需手动编写大量数据访问代码。EF允许开发者通过.NET对象模型来操作数据库。Entity Framework Core...

    EntityFrameworkCore.zip

    在“EntityFrameworkCore.zip”这个压缩包中,可能包含了一些示例代码或者教程,帮助开发者了解如何在EF Core项目中集成和使用这个映射库。学习这些内容可以帮助开发者更好地理解如何在实践中应用EF Core和对象映射...

    Programming Entity Framework DbContext

    在本篇详细知识点讲解中,将基于给定文件信息,深入探讨Entity Framework(实体框架)中Code First方法的相关知识点。根据文件标题《Programming Entity Framework DbContext》和描述,该文件应该是关于Entity ...

    Z.EntityFramework.Extensions.EFCore.dll

    Z.EntityFramework.Extensions.EFCore 破解 ,支持.NET Core 3.1批量插入数据,速度很快。

    EntityFramework.SqlServer_EntityFramework_

    1. `EntityFramework.SqlServer.dll`:这是实际的DLL文件,包含了实现EF与SQL Server交互的代码和功能。在.NET项目中,你可以通过引用这个DLL来使用封装后的EF服务。 2. `EntityFramework.SqlServer.xml`:这是一个...

    Entity Framework学习笔记

    本篇学习笔记主要关注的是Entity SQL(E-SQL),这是EF提供的一种结构化查询语言,类似于标准的SQL,但设计用于与EF一起工作。E-SQL并不支持直接的Insert、Update、Delete操作,这意味着开发者不能像在常规SQL中那样...

    Entity Framework 学习(中文资料初中高级共14篇) pdf格式

    本套学习资料包括了初级、中级和高级三个阶段的教程,共计14篇文章,以PDF格式提供,非常适合希望系统学习和提升EF技术的C#开发者。 初级篇通常会介绍以下基础知识: 1. **ORM概念**:解释什么是ORM,为什么我们...

    Entity Framework 学习

    Entity Framework(EF)是Microsoft开发的一个对象关系映射(ORM)框架,用于.NET应用程序,它允许开发者使用.NET语言(如C#或VB.NET)来操作数据库,而无需编写大量的SQL语句。通过EF,开发者可以将数据库操作抽象...

    EntityFramework.dll

    描述中提到的"EntityFramework.dll"是EF框架的实现库,它是运行时组件,包含了所有EF功能的实现代码。在.NET项目中引用这个DLL,开发者就可以利用EF的强大功能,如数据库迁移、LINQ查询、数据库上下文等。 标签"EF...

    Z.EntityFramework.Extensions破解 注册机

    Z.EntityFramework.Extensions 破解 注册机,详细破解方法

    Z.EntityFramework.Plus.EF6兼容Entity Framework Profiler和MiniProfiler

    如果使用Entity Framework也用了Z.EntityFramework.Plus.EF6且同时使用Entity Framework Profiler或MiniProfiler监控EF生成的SQL,你可能会遇到他们不兼容的问题,原因是Z.EntityFramework.Plus.EF6识别数据库类型...

    Entity Framework 4 In Action

    - **全面覆盖**:本书不仅涵盖了EF4的基础概念和核心功能,还深入探讨了许多高级主题,适合不同层次的读者学习。 - **实战导向**:通过大量的实例代码和应用场景分析,帮助读者快速掌握EF4的实际应用技巧。 - **专家...

    Entity Framework 学习.rar

    通过深入学习和实践Entity Framework,开发者可以更加高效地进行数据操作,减少与数据库的直接交互,提高代码的可维护性和可读性。同时,由于ORM框架的存在,开发者可以更加专注于业务逻辑,而不是数据库的细节。...

Global site tag (gtag.js) - Google Analytics