如何为 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 之外,这似乎并没有太大的不同。