改善EF代码的方法(上)

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

> MergeOption.NoTracking

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

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();

    }
}

> GetObjectByKey/First

GetObjectByKey:
在EF中,使用GetObjectByKey方法获取数据时,它首先会查询是否有缓存,如果有缓存则从缓存中返回需要的实体。如果没有则查询数据库,返回需要的实体,并添加在缓存中以便下次使用。
First: 总从数据库中提取需要的实体。
因此,我们应在合适的地方选择GetObjectByKey方法来获取数据,以减少对数据库的访问提升性能。示例代码如下:

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而不是抛异常。示例代码如下:

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);
    }
}

> First /FirstOrDefault

First: 当我们使用First来获取数据,如果没有符合条件的数据,那么我们的代码将会抛出异常。
FirstOrDefault: 当我们使用FirstOrDefault来获取的数据,如果没有符合条件的数据,那么它将返回null。
显然,对于一个良好的代码,是对可以预见的异常进行处理,而不是等它自己抛出来。示例代码如下:

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);
    }
}

> 延迟加载/Include

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

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方法,如下代码所示:

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将被加载。

> 根据外键得到主键的实体

public static void WaiJianTest()
{
    var stu = me.Student;

    foreach (var s in stu)
    {
    Console.WriteLine(s.StudentID);
    Console.WriteLine(s.Class.ClassName);
    Console.WriteLine("---------");
    }
}

其中 Class 为主键类,ClassName是主键的属性

时间: 2024-11-07 12:52:17

改善EF代码的方法(上)的相关文章

改善EF代码的方法(下)

本节,我们将介绍一些改善EF代码的方法,包括编译查询.存储模型视图以及冲突处理等内容. > CompiledQuery 提供对查询的编译和缓存以供重新使用.当相同的查询需要执行很多遍的时候,那么我们可以使用ComplieQuery将查询的语句进行编译以便下次使用,这样可以免去对同一语句的多次处理,从而改善性能.示例代码如下: public void ComplieTest() { using (var db = new NorthwindEntities1()) { //对查询进行编译 var

idea格式化代码把方法上的文字注释换行的问题

在用idea模板的/** 生成方法注释,生成之后: /** * 分页查询 * @param page * @param size * @return */ 然后有的时候如果代码想用快捷键(CTRL + ALT + L)格式化之后,注释就会变成这样: /** * 分页查询 * * @param page * @param size * @return */ 在文字区域自动换行了,修改设置之后就可以改回来: 步骤: File>Settings>Editor>Code Style>Jav

Entity Framework SqlFunctions 教你如何在EF调用sqlserver方法的函数存根

今天算是研究了一天的SqlFunctions,请教了几个群的牛人,居然发现大伙对这个都比较陌生, 有的甚至直指EF中是不能调用sqlserver里的方法的. 因为之前搞过linq to sql 里面的SqlMethod ,所以觉得EF里面必须是可以的. 首先需要简短介绍一下EF6和EF5,当你NuGet一个EF5的包的时候,只有EntityFramework,而EF6确有EntityFramework和EntityFramework.SqlServer, 这2者是有很大区别的. 在EF5环境下,

《代码阅读方法与实践》阅读笔记之二

时间过得真快,一转眼,10天就过去了,感觉上次写阅读笔记的场景仿佛还历历在目.<代码阅读方法与实践>这本书真的很难写笔记,本来我看这本书的名字还以为书里大概写的都是些代码阅读的简易方法,心想着这就好写笔记了,没想到竟然好多都是我们之前学过的东西,这倒让我有点无从下手了.大概像我们这些还没有太多经历的大学生,总是习惯于尽量避免自己的工作量,总是试图找到一些完成事情的捷径吧.总之,尽管我不想承认,但我自己心里很清楚,我就是这种人.下面开始言归正传,说说接下来的几章内容归纳. 这本书在前面已经分析了

opensips/kamailio gdb代码调试方法详解

 要对kamailio/opensips进行单步调试,就需要先了解其代码的结构及运行方式,kamailio/opensips使用Reactor和Proactor结合的IO网络模型,使用主进程负责监听网络,当有连接产生或首包到达时,就通过pipe将文件描述符发送给worker进程,worker进程就会负责此连接的数据取读.业务处理.数据发送等事情,然后再次等待此socket事件.当我们想要调试一段代码时,就先确认这段代码是运行在什么类型的进程中,通常用于处理SIP逻辑的代码都是在worker进

《代码阅读方法与实践》阅读笔记三

之前已经看完了<代码阅读方法与实践>的前六章,基本上也就是看得比较粗略,没有很精细的阅读,上节课听到老师说的“学术交流会”还是很紧张的,挺害怕被问到问题,结果回答不出来可怎么办啊,不仅丢人,分也送给别人了啊,这可怎么破啊.所以呢,我打算近期再看一遍,不管有没有用,算是给自己加点自信吧. 第七章,讲的是编程规范和约定,主要就是文件的命名及组织.缩进.编排.命名约定.编程实践.过程规范之类的,其实这一章也不用我做过多的介绍,因为大家应该都有听各科老师讲过好几遍了,道理大家都懂,但是大家除了在理论上

《代码阅读方法与实践之读书笔记之一》

阅读代码是程序员的基本技能,同时也是软件开发.维护.演进.审查和重用过程中不可或缺的组成部分.<代码阅读方法与实践之读书笔记之一>这本书围绕代码阅读,详细论述了相关的知识与技能.我希望通过仔细阅读并学习本书,可以快速地提高我的代码阅读的技能与技巧,进而从现有的优秀代码.算法.构架.设计中汲取营养,提高自身的开发与设计能力.此次读了此书的前四章,以下是我从中汲取到的宝贵养分: 从第一章<导论>一节中我体会到了我们要养成一个经常花时间阅读别人编写的高品质代码的习惯,因为阅读高品质的代码

Zen Coding: 一种快速编写HTML/CSS代码的方法[Emmet]

译自:[Smashing Magazine](http://www.smashingmagazine.com/2009/11/21/zen-coding-a-new-way-to-write-html-code/)中文:[Zen Coding: 一种快速编写HTML/CSS代码的方法](http://www.qianduan.net/zen-coding-a-new-way-to-write-html-code.html) 请尊重版权,转载请注明来源! - - - - - - 在本文中我们将展示

钩取API之代码修改方法【一】

IAT方式就不去花精力了,加了壳的程序用这方法压根用不上. 就熟悉一下代码修改方法.书上用的是隐藏进程的实例 第一种办法 一,枚举进程,给所有进程加载DLL[用远程线程注入] 二,传入需要隐藏的进程名 三,判断有没有修改过需要钩取的函数,如果还没有修改过就改掉,跳向自己的函数,同时保存好原来的值 四,在自己的替代函数里将原来的值修改回去,并再执行一次,执行完做相关处理 五,在自己的替代函数最后再钩取函数,修改跳转到替代函数 基本逻辑就是这样,像是移花接木啊... DLL代码: #define S