MVC3使用EF4.3和依赖注入问题

时间:2012-08-26 18:44:45

标签: asp.net-mvc-3 entity-framework dependency-injection

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

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

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

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

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
            });
        }
    }

由于我使用了依赖性注射,这是一个问题还是还有其他问题我误解了?

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

非常感谢。

2 个答案:

答案 0 :(得分:2)

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

你想要做的是通过一个接口使用你的数据库,看到你正在使用DI,你可以在控制器的构造函数中注入DbContext类的引用,让DI控制器执行为你工作。

最好通过传递定义DbContext的接口将定义存储库的接口传递给Controller,这是因为使后者的接口很容易变得过于复杂,而坚持存储库则很多简单。为简单起见,我首先直接使用DbContext,然后从那里扩展。

问题2:

包含需要将表的名称包含为字符串。所以后者使用Include是正确的,而前者则不然。

如果我没记错的话,你可以这样做:“。包括(i =&gt; i.ExampleRoles.Name)”来实现同样的目的。

答案 1 :(得分:1)

是的,提取您的数据库层(存储库/上下文)然后将其注入您的业务层(控制器)是非常正常的,这是未来证明您的应用程序的好方法。如果您想将数据库ORM从实体框架更改为其他内容,该怎么办?将它与控制器紧密结合会产生巨大的麻烦。

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

<{1}} Include使用lambdas dbset中的扩展名System.Data.Entity。如果要使用它,则需要包含该引用。