2

我最近一直在使用 Entity Framework 4.3 和依赖注入来学习 MVC3,因此我可以在以后实现单元测试。我现在正在尝试实现一些我在各种示例中看到的功能,但是我遇到了一些似乎源于我使用依赖注入的问题,因此我希望有人指出我哪里出错了。

我的第一个问题很简单;在我见过的大多数 MVC3 示例中,对数据库的访问是在控制器中完成的,但是当使用依赖注入时,我似乎需要将此代码重构到已实现的存储库中。这是正常和正确的吗?

我的第二个更深入的问题是处理这个简单的例子:

我的存储库类中有这个方法,它几乎是从在线示例(此处)复制而来的。但是我收到关于该部分的错误Include,并且智能感知确实说该变量需要是一个字符串。我已经尝试了前面提到的链接中的原始代码,并且效果很好,该项目之间的唯一主要区别是我使用的是依赖注入。

public ExampleUser GetStruContractUser(int id)
{
    ExampleUser user = context.ExampleUsers
        .Include(i => i.ExampleRoles)
        .Where(i => i.UserID == id)
        .Single();

    return user;
}

将参数更改Include为以下工作正常。

public ExampleUser GetStruContractUser(int id)
{
    ExampleUser user = context.ExampleUsers
        .Include("ExampleRoles")
        .Where(i => i.UserID == id)
        .Single();

    return user;
}

作为参考,这是我正在使用的 DbContext 类:

public class EFDbContext : DbContext
{
    public DbSet<ExampleUser> ExampleUsers { get; set; }
    public DbSet<ExampleRole> ExampleRoles { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Entity<ExampleUser>().ToTable("User", "MySchema");
        modelBuilder.Entity<ExampleRole>().ToTable("Role", "MySchema");

        modelBuilder.Entity<ExampleUser>()
            .HasMany(m => m.ExampleRoles)
            .WithMany(t => t.ExampleUsers)
            .Map(a =>
            {
                a.MapLeftKey("UserID");  // your PK column name in user table
                a.MapRightKey("RoleID"); // your PK column name in role table
                a.ToTable("UserRole", "MySchema");  // your join table name
            });
        }
    }

这是由于我使用依赖注入导致的问题,还是我误解了其他事情?

如果您需要更多信息,请询问,我会尽力提供。

非常感谢。

4

2 回答 2

2

问题 1: 使用 DI 并不强制您使用存储库模式,实际上它们是不相关的。这只是避免将控制器类与数据库上下文类紧密耦合并因此能够更轻松地测试这些类的好方法。存储库使您能够隐藏您如何访问数据库的实现细节,并允许您切换 ORM:s 如果发生这种情况(它永远不会发生)。Repository 依赖于您为 DbContext 提供接口,使用 DI 也是如此。

您想要做的是通过接口使用您的数据库,并且看到您正在使用 DI,您可以在控制器的构造函数中注入对 DbContext 类的引用,并让 DI 控制器为您完成工作.

将定义存储库的接口传递给控制器​​优于传递定义 DbContext 的接口的原因是,使后者的接口很容易变得过于复杂,而坚持使用存储库要简单得多。不过,为了简单起见,我将从直接使用 DbContext 开始,然后从那里扩展。

问题2:

Include 需要包含表的名称作为字符串。所以你后面对 Include 的使用是正确的,而前者不是。

如果我没记错的话,你可以这样做:".Include(i => i.ExampleRoles.Name)" 来实现同样的目的。

于 2012-08-26T19:16:13.223 回答
1

是的,提取您的数据库层(存储库/上下文)然后将其注入您的业务层(控制器)是非常正常的,并且是未来证明您的应用程序的好方法。如果您想将数据库 ORM 从实体框架更改为其他东西怎么办?将它与您的控制器紧密耦合会让人头疼。

您的第二个问题 withinclude与依赖注入无关。

Includedbset使用 lambdas 中的扩展System.Data.Entity。如果您想使用它,您需要包含该参考。

于 2012-08-26T19:22:11.317 回答