如何为 DevForce 中的 POCO class 访问 NamedQuery 运行 上的 EntityManager
How to access the EntityManager that the NamedQuery is running on for a POCO class in DevForce
我正在一个基于 DevForce 的应用程序中编写一个 POCO class,它有许多命名查询,但我不知道如何从命名查询内部访问实体管理器。
我已经从下面的实体管理器部分中放置了缩短的代码:
public partial class BearPawEntities
{
public EntityQuery<OrderView3> OrderView3s()
{
return new EntityQuery<OrderView3>("OrderView3s", this);
}
}
这是我在编写较重的查询之前尝试使其正常工作的基本内容之一:
[EnableClientAccess]
public class PocoServiceProvider
{
public PocoServiceProvider() { }
public IQueryable<OrderView3> GetOrderView3s()
{
var currentUser = new EntityQuery<User>().Include(u => u.Role.RoleCheckPoints).Include(u => u.CoveringForUsers)
.FirstOrDefault(u => u.UserName == System.Threading.Thread.CurrentPrincipal.Identity.Name);
List<OrderView3> orderView3s = new List<OrderView3>();
for (int i = 1; i < 150; i++)
{
orderView3s.Add(new OrderView3()
{
Id = i,
CustomerCode = $"Customer {i}",
Invoices = i
});
}
return orderView3s.AsQueryable();
}
...
}
如果我删除获取当前用户的代码,那么我的示例就可以工作,并且我将列表返回给客户端,但是每当我尝试调用新的 EntityQuery<> 函数时,我都会收到一个异常,详细信息为 {"No EntityManager for this query"}.
我曾尝试将 EntityManager 作为参数传入,但后来我被告知它不可序列化(这是我所期望的)。我已经在 BearPawEntities class 中的代码中设置了 query.EntityManager 属性,但在我看来,这更能让您在需要时使用不同的管理器,而不是将其传递给查询。
我还尝试了在 DevForce 文档的示例中看到的扩展方法。
在这一点上,我很困惑,希望得到任何帮助!
非常感谢
李
DevForce 在 "client-side" 和 "server-side" 之间保持非常严格的区别,并且永远不会将客户端 EntityManager
传递给服务器。当您看到服务器端 EntityManager
,由 DevForce 作为方法参数或 属性 注入时,这是为该单一目的创建的 EM 的新实例。
这并不意味着您不能创建自己的新实例,您只需要注意创建它的方式即可。当 DF 创建服务器端 EM 时,它被认为已经通过身份验证,因此不会通过 IEntityLoginManager
,并且它还使用对 EntityServer
的简单方法调用而不是 WCF。身份验证问题可能会很棘手,具体取决于您的实现(自定义组合上下文可以帮助解决此问题),但您还应该使用 EntityServiceOption.UseLocalService
选项设置来构建 EM,以避免 WCF 开销。
命名查询的工作流程与其他查询略有不同。通常,您可以使用 EntityServerQueryInterceptor
来控制授权和过滤,但在拦截器之前调用命名查询方法。这意味着将执行授权 "late",如果您需要使用用户身份进行 build/execute 查询,可能会晚于预期时间。
解决此问题的方法可能是在 IEntityLoginManager
实施中使用自定义 IPrincipal
以确保授权查询(和保存)所需的所有信息都可以直接从线程的 CurrentPrincipal
,DF 将始终为请求设置。这样做可以避免每次执行查询时都必须重新查询用户信息。
我认为如果命名查询(或 class/etc)装饰有 [RequiresAuthentication],那么拥有一个假设它已通过身份验证的 EM 就很好。我相信所缺少的只是在命名查询中创建一个新的 EM。
我知道线程的 CurrentPrincipal 已经填充了所需的自定义 IPrincipal(因为我与 OP 在同一个项目上工作),它与服务器方法委托一起工作得很好。除了那些自动注入 EM 之外,这似乎并没有太大的不同。
我正在一个基于 DevForce 的应用程序中编写一个 POCO class,它有许多命名查询,但我不知道如何从命名查询内部访问实体管理器。
我已经从下面的实体管理器部分中放置了缩短的代码:
public partial class BearPawEntities
{
public EntityQuery<OrderView3> OrderView3s()
{
return new EntityQuery<OrderView3>("OrderView3s", this);
}
}
这是我在编写较重的查询之前尝试使其正常工作的基本内容之一:
[EnableClientAccess]
public class PocoServiceProvider
{
public PocoServiceProvider() { }
public IQueryable<OrderView3> GetOrderView3s()
{
var currentUser = new EntityQuery<User>().Include(u => u.Role.RoleCheckPoints).Include(u => u.CoveringForUsers)
.FirstOrDefault(u => u.UserName == System.Threading.Thread.CurrentPrincipal.Identity.Name);
List<OrderView3> orderView3s = new List<OrderView3>();
for (int i = 1; i < 150; i++)
{
orderView3s.Add(new OrderView3()
{
Id = i,
CustomerCode = $"Customer {i}",
Invoices = i
});
}
return orderView3s.AsQueryable();
}
...
}
如果我删除获取当前用户的代码,那么我的示例就可以工作,并且我将列表返回给客户端,但是每当我尝试调用新的 EntityQuery<> 函数时,我都会收到一个异常,详细信息为 {"No EntityManager for this query"}.
我曾尝试将 EntityManager 作为参数传入,但后来我被告知它不可序列化(这是我所期望的)。我已经在 BearPawEntities class 中的代码中设置了 query.EntityManager 属性,但在我看来,这更能让您在需要时使用不同的管理器,而不是将其传递给查询。
我还尝试了在 DevForce 文档的示例中看到的扩展方法。
在这一点上,我很困惑,希望得到任何帮助!
非常感谢
李
DevForce 在 "client-side" 和 "server-side" 之间保持非常严格的区别,并且永远不会将客户端 EntityManager
传递给服务器。当您看到服务器端 EntityManager
,由 DevForce 作为方法参数或 属性 注入时,这是为该单一目的创建的 EM 的新实例。
这并不意味着您不能创建自己的新实例,您只需要注意创建它的方式即可。当 DF 创建服务器端 EM 时,它被认为已经通过身份验证,因此不会通过 IEntityLoginManager
,并且它还使用对 EntityServer
的简单方法调用而不是 WCF。身份验证问题可能会很棘手,具体取决于您的实现(自定义组合上下文可以帮助解决此问题),但您还应该使用 EntityServiceOption.UseLocalService
选项设置来构建 EM,以避免 WCF 开销。
命名查询的工作流程与其他查询略有不同。通常,您可以使用 EntityServerQueryInterceptor
来控制授权和过滤,但在拦截器之前调用命名查询方法。这意味着将执行授权 "late",如果您需要使用用户身份进行 build/execute 查询,可能会晚于预期时间。
解决此问题的方法可能是在 IEntityLoginManager
实施中使用自定义 IPrincipal
以确保授权查询(和保存)所需的所有信息都可以直接从线程的 CurrentPrincipal
,DF 将始终为请求设置。这样做可以避免每次执行查询时都必须重新查询用户信息。
我认为如果命名查询(或 class/etc)装饰有 [RequiresAuthentication],那么拥有一个假设它已通过身份验证的 EM 就很好。我相信所缺少的只是在命名查询中创建一个新的 EM。
我知道线程的 CurrentPrincipal 已经填充了所需的自定义 IPrincipal(因为我与 OP 在同一个项目上工作),它与服务器方法委托一起工作得很好。除了那些自动注入 EM 之外,这似乎并没有太大的不同。