我最近一直在使用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
});
}
}
由于我使用了依赖性注射,这是一个问题还是还有其他问题我误解了?
如果您需要更多信息,请询问,我会尽力提供。
非常感谢。
答案 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
与依赖注入无关。
Include
使用lambdas dbset
中的扩展名System.Data.Entity
。如果要使用它,则需要包含该引用。