【问题标题】:How could I access special functions baked into a Custom DbContext through a Generic DbContext which lives within a Generic Repository?如何通过位于通用存储库中的通用 DbContext 访问自定义 DbContext 中的特殊功能?
【发布时间】:2013-08-14 08:34:41
【问题描述】:

这是我到目前为止的设置:

  • 数据库优先实体框架(生成 EDMX)
    • 将 POCO 分离到不同的项目中
    • 在 EDMX 下留下 Custom DbContext 用作有界 Countext
  • 创建了一个 UOW
  • 创建了一个通用存储库 (IRepository)
  • 通过 IRepository 的具体实现将每个实体映射到 UOW
    • UOW 实例化由 EDMX 创建的 Custom DbContext 并将其传递给每个存储库

到目前为止一切都很好。

现在,问题出在最后一部分。 UOW 实例化 Custom DbContext,将其注入到 Repositories 中,一切正常……大部分情况下。

每个 Repository 实现都采用 DbContext,创建一个 DbSet 并公开通常的 CRUD 操作。所有实体都可以通过泛型访问,所以如果我想实现说 GetAll() 我将简单地返回 DbSet 并且它已经被映射到实体。

但是,当我尝试从存储库中的 DbContext 访问函数导入时...我不能。

我当然不能这样做是有道理的:通用存储库将 DbContext 作为输入,但它对 EDMX 创建的 Custom DbContext 一无所知,因此,所有这些函数都添加到自定义 DbContext 不为存储库中的 DbContext 所知。

换句话说:

  • 我可以在 UOW 中从 Custom DbContext 访问函数导入
  • 我将 Custom DbContext 传递给每个实体存储库的构造函数
  • 存储库需要从 DbContext 派生的任何类,因此 自定义 DbContext 可以解决问题
  • 当存储库尝试通过 DbContext 访问函数导入时,它不能访问,因为它不知道它们

显然我不能在任何地方都使用 Custom DbContext,因为我会将存储库与 特定 Custom DbContext 结合起来,并且我需要不止一个,因为我创建了多个有界上下文。

唉,问题: 我如何从存储库中调用函数导入而不将其与特定的 Custom DbContext 结合?

解决方法:

我知道我可以使用反射,但出于性能原因,我试图摆脱它(我知道它并不那么糟糕,但仍然......目前的问题是寻找更好的方法)。

我已经设法使用 DbContext.SqlQuery() 来执行存储过程(映射到 EDMX 中的函数导入)。再说一次,因为我可以轻松地在 EDMX 中交换函数导入,所以我想找到一种在存储库中访问它的方法。

希望这一切都有意义。我很感激任何人都可以解决这个问题。

【问题讨论】:

    标签: entity-framework inheritance dbcontext unit-of-work ddd-repositories


    【解决方案1】:

    我不清楚你怎么知道要调用什么函数或它需要什么参数。但是,您可以查看为函数导入生成的代码,它基本上看起来像这样:

    ((IObjectContextAdapter)this).ObjectContext
         .ExecuteFunction<Customer>("Customers_With_Recent_Orders", customerId)
    

    因此(而不是使用反射)你可以动态地做同样的事情——即使使用反射你也必须知道要调用什么函数,你应该知道你期望的实体的类型,你可以使用@987654323 @ 传递任意数量的参数应该是可行的。

    ** 编辑 **

    你也可以使用其他重载将函数作为不跟踪来执行:

    ((IObjectContextAdapter)this).ObjectContext
         .ExecuteFunction<Customer>(
             "Customers_With_Recent_Orders", 
             MergeOption.NoTracking, 
             customerId)
    

    【讨论】:

    • 我喜欢这种方法,确实非常巧妙,但与我已经拥有的return _dbSet.SqlQuery("GetPosts @Language", new SqlParameter("Language", Language.ToString())).AsNoTracking(); 相比,我似乎并没有向前迈出多少步。此外,通过DbSet.SqlQuery,我可以使用.AsNoTracking(),它有时会变得非常有用(出于性能原因)。就目前而言,我还没有找到一种方法来调用导入的函数,而不必在需要它的任何地方手动重建它,而不是从 EDMX 中检索它并在其中传播更改自己的
    • 不同之处在于,在您的情况下,您开始在您的应用程序中重新引入 SQL,而 EF 试图隐藏它。可能没问题 - 视情况而定。您还可以通过使用不同的重载将函数作为不跟踪来执行。我更新了帖子以显示如何执行此操作。随意支持 DbContext 中的存储过程:data.uservoice.com/forums/…
    • 我喜欢IObjectContextAdapter 中的MergeOption.NoTracking。不知道有没有。
    • 按照您的建议,我赞成 "Code First 对存储过程的支持"。然而,我选择 DB First 的原因之一正是能够使用存储过程。我的情况是,由于 类继承 难题,我无法访问此类 Imported Functions
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 1970-01-01
    相关资源
    最近更新 更多