对象查询(实体框架)

ObjectQuery 泛型类表示一个查询,此查询返回由零个或零个以上类型化实体对象组成的集合。对象查询总是属于现有对象上下文。此上下文提供了编写和执行查询所需的连接和元数据信息。类型化 ObjectContext 包含一组返回类型化 ObjectQuery 实例的属性。模型中的每个实体类型都有其中的一个属性。使用这些属性可以更容易地创建类型化 ObjectQuery 的实例。在以下方案中将执行对象查询:

  • 对其执行操作时,例如 foreach (C#) 或 For Each (Visual Basic) 枚举期间。

  • 分配用于填充 List 集合时。

  • 显式调用 Execute 方法时。

  • 调用 LINQ 查询执行运算符(例如 FirstAny)时。有关更多信息,请参见查询生成器方法(实体框架)

下面的查询返回一个 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 类型,该类型可以是嵌套结果或者匿名类型。简单类型(例如 Int32String)与返回单个属性值的投影一起使用。

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 上的 GetObjectByKeyTryGetObjectByKey 方法将具有指定 EntityKey 的对象返回到对象上下文。使用 GetObjectByKey 时,如果提供的 EntityKey 与现有实体不对应,则必须处理 ObjectNotFoundException。有关更多信息,请参见如何:使用特定对象的键返回该对象(实体框架)

另请参见

概念

以对象形式查询数据(实体框架)