对象查询(实体框架)
ObjectQuery 泛型类表示一个查询,此查询返回由零个或零个以上类型化实体对象组成的集合。对象查询总是属于现有对象上下文。此上下文提供了编写和执行查询所需的连接和元数据信息。类型化 ObjectContext 包含一组返回类型化 ObjectQuery 实例的属性。模型中的每个实体类型都有其中的一个属性。使用这些属性可以更容易地创建类型化 ObjectQuery 的实例。在以下方案中将执行对象查询:
对其执行操作时,例如 foreach (C#) 或 For Each (Visual Basic) 枚举期间。
分配用于填充 List 集合时。
显式调用 Execute 方法时。
调用 LINQ 查询执行运算符(例如 First 或 Any)时。有关更多信息,请参见查询生成器方法(实体框架)。
下面的查询返回一个 Contact 对象,该对象的名字和姓氏由传递的参数指定:
' Get the contacts with the specified name.
Dim contactQuery As ObjectQuery(Of Contact) = _
context.Contact _
.Where("it.LastName = @ln AND it.FirstName = @fn", _
New ObjectParameter("ln", lastName), _
New ObjectParameter("fn", firstName))
// Get the contacts with the specified name.
ObjectQuery<Contact> contactQuery = context.Contact
.Where("it.LastName = @ln AND it.FirstName = @fn",
new ObjectParameter("ln", lastName),
new ObjectParameter("fn", firstName));
有关如何使用对象上下文编写和执行查询的完整示例,请参见如何:执行返回实体类型的查询(实体框架)。有关 Entity SQL 查询的更多信息,请参见 Entity SQL 语言。
查询投影
当对象查询用于以实体对象形式返回 实体数据模型 (EDM) 数据时,对象查询还支持投影,投影返回的数据很难具体化成实体类型。ObjectQuery 为返回非实体类型的投影使用 DbDataRecord 类型,该类型可以是嵌套结果或者匿名类型。简单类型(例如 Int32 或 String)与返回单个属性值的投影一起使用。
Select 查询生成器方法返回 ObjectQuery,当执行该查询时,将返回 DbDataRecord 对象的集合。LINQ to Entities 和 Entity SQL 都支持查询投影。有关查询投影的示例,请参见下面的主题:
以下注意事项适用于查询投影:
可以对 ObjectQuery 进行初始化,使之表示单个标量结果而不是标量结果集合。某些扩展方法要求使用集合结果作为输入。在这种情况下,当调用其中的一个方法时将引发 ArgumentException,如下面的示例所示。
' Define a query projection that returns ' a single scalar value rather than a collection. Dim scalarQuery As ObjectQuery(Of Int32) = _ New ObjectQuery(Of Int32)("100", advWorksContext) ' Calling an extension method that requires a collection ' will result in an exception. Dim hasValues As Boolean = scalarQuery.Any()
// Define a query projection that returns // a single scalar value rather than a collection. ObjectQuery<Int32> scalarQuery = new ObjectQuery<Int32>("100", advWorksContext); // Calling an extension method that requires a collection // will result in an exception. bool hasValues = scalarQuery.Any();
如果 ObjectQuery 可能在投影到某个基元类型时返回 null 值,则应使用该类型的可为 null 的版本。下面的查询使用可为 null 的 DateTime,因为 SalesOrderHeader 对象的 ShipDate 属性可能返回 null 值。
Dim shipDateQuery As ObjectQuery(Of Nullable(Of Date)) = _ advWorksContext.SalesOrderHeader _ .Where("it.CustomerID = @contactId", _ New ObjectParameter("contactId", contactId)) _ .SelectValue(Of Nullable(Of Date))("it.ShipDate")
ObjectQuery<Nullable<DateTime>> shipDateQuery = advWorksContext.SalesOrderHeader .Where("it.CustomerID = @contactId", new ObjectParameter("contactId", contactId)) .SelectValue<Nullable<DateTime>>("it.ShipDate");
有关更多信息,请参见可为 null 的类型(Visual Basic 编程指南)或可以为 null 的类型(C# 编程指南)。
设置命令超时
对象查询和 SaveChanges 操作的默认超时由基础连接提供程序定义。但是,可以通过在 ObjectContext 上使用 CommandTimeout 属性重写此默认超时值,如下面的示例所示。
' Specify a timeout for queries in this context, in seconds.
context.CommandTimeout = 120
// Specify a timeout for queries in this context, in seconds.
context.CommandTimeout = 120;
当查询很复杂或者由于其他性能问题导致对 SaveChanges 的查询或调用频繁超时时,可以执行此操作。
查看存储命令
查询 EDM 时,实体框架 将基于 EDM 的 LINQ to Entities 和 Entity SQL 查询转换为对数据源的等效查询。对象服务提供 ToTraceString 方法,使用该方法可以在运行时为 ObjectQuery 查看这些存储命令,而不必对数据源运行跟踪。EntityClient 提供程序还在 EntityCommand 上提供了 ToTraceString 方法。有关更多信息,请参见如何:查看存储命令(实体框架)。
通过对象的 EntityKey 检索对象
如果知道实体的键值,则可以从数据源中检索该实体,而无需显式创建并执行对象查询。ObjectContext 上的 GetObjectByKey 和 TryGetObjectByKey 方法将具有指定 EntityKey 的对象返回到对象上下文。使用 GetObjectByKey 时,如果提供的 EntityKey 与现有实体不对应,则必须处理 ObjectNotFoundException。有关更多信息,请参见如何:使用特定对象的键返回该对象(实体框架)。