Entity Framework 4 in Action读书笔记——第三章:查询对象模型基础(2)

三、对类进行查询

因为数据库对EDM是完全抽象的,你可以完全忽略底层的数据库结构对类进行查询。EF使用映射信息转换查询成SQL。工作流如下:

image

类和数据库之间的抽象不难理解。如果一个属性和数据表列的名称不匹配,你仍然可以在你的查询里使用属性名——这在类查询时非常明显。使用LINQ to Entities,你不太可能输入错误的名称,因为VS的智能提示给你提示正确的名称。更重要的是,如果你键入一个不正确的属性名,编译器会抛出一个异常。

其他情况可以导致数据库和对象模型的不同。Customers和Suppliers有自己的类,但只有一个表存储它们的数据。再次,你对这些实体类进行查询而不是对Company表。

此外,我们已经把地址信息组合成一个复杂类型。当查询时,它们像类型的一部分进行访问,然而在数据库中它们是清晰地列。

起初,这些差异可能会蒙蔽你的眼睛,尤其是你熟悉关系模型。但是经过一些实践,你会发现这种方式的查询比SQL查询更直观和有效。类表示业务场景比关系模型更有意义,结果是对类查询比SQL查询更面向业务。更重要的时,类之间的错综复杂的关系由EF处理,你不需要关心数据的物理关联。

四、从数据库中检索数据

当你执行一个查询,LINQ提供托管实体集解析查询,并创建一个命令树。因为你正在写对类的查询,命令树代表概念上的查询。对象服务将命令树传给Entity Client,在映射和存储文件的帮助下,转换命令树为本地SQL命令。Entity Client使用ADO.NET 提供程序(在connectionString属性的provider节指定)启动SQL对数据库查询,并获得结果。然后查询结果形成表格的形式反映对象模型的结构。最后数据返回到对象服务层。下图说明了这一过程:

E{MYB}}3E%V{IJ2A3)AL_47

在添加scalar, complex和 reference属性之后,处理集合属性之前,上下文触发ObjectMaterialized事件。这个事件接受正在具体化的实体,在对象返回给程序之前允许你执行一些逻辑。下面的代码向你展示如何使用这一事件。

public OrderITEntities()
{
    ctx.ObjectMaterialized +=
    new ObjectMaterializedEventHandler(ctx_ObjectMaterialized);
}
void ctx_ObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
{
    var o = entity as Order;
    //any logic
}

五、捕获生成的SQL

虽然实体框架生成SQL代码,但是你不能假设代码都是好的。你必须始终确保执行生成的代码不需要太多的数据库资源。有时候,生成的查询太过繁重和复杂,你可以通过存储过程或者手动写SQL获得更好的性能。

检查SQL最简单的方法是使用 profiler工具。使用这个工具,您可以监视所有对数据库执行的语句,然后分析需要细化或完全替代的语句。通常,这种监测需要高级的数据库权限,有时你并没有这种权限。幸运的是,对象服务层使用ObjectSet<T>类的ToTraceString方法可以帮助你。下面是怎么使用它

var result = ctx.Orders.Where(o => o.Date.Year == DateTime.Now.Year);
var SQL = (result as ObjectQuery).ToTraceString();

六、查询何时执行?

通常来说,LINQ查询当程序代码访问数据时执行。每次LINQ to Entities执行查询时,EF访问数据库并取回数据。当把数据从记录转换成对象时,LINQ to Entities会扫描内存中看对象是否存在,如果存在,就返回内存中的对象,如果不存在,就将记录转换成对象,放入内存并返回。

让我们看一个例子。假设你必须遍历两次查询结果,如下:

var result = LINQToEntitiesQuery;
foreach(var o in result)
{
     ...
}
foreach(var o in result)
{
     ...
}

每次foreach执行时,就会触发对数据库的往返操作。上下文不关心你是否已经执行了相同的查询。

如果不是简单的查询所有的订单,而是更复杂的查询,两次执行表示存在严重的性能问题。简单的解决办法是第一次强制执行,然后把对象下载到内存中。然后在内存中遍历集合,这样就不用对数据库来回访问两次了。下面是代码:

var result = LINQToEntitiesQuery.ToList();
foreach(var o in result)
{
     ...
}
foreach(var o in result)
{
     ...
}

这个方法不仅适用于返回对象列表,还适用于返回一个单独的对象。EF使查询返回一个对象和一个集合没有什么区别。

七、从上下文管理数据库

ObjectContext类由四个有趣的方法让你操作数据库结构:

CreateDatabase—使用连接字符串和SSDL信息创建数据库

CreateDatabaseScript—使用SSDL信息生成数据库脚本

DatabaseExists—验证指定连接字符串的数据库是否存在

DeleteDatabase—使用指定的连接字符串删除数据库

当创建一个应用程序不创建安装包时,这些方法很有用。当程序启动时,如果数据库不存在可以使用DatabaseExists和CreateDatabase创建数据库。

原文地址:https://www.cnblogs.com/nianming/p/2145547.html