EF迁移应该去哪里,我的类库项目还是我的ASP.NET项目?

时间:2015-03-10 21:45:44

标签: c# asp.net entity-framework ef-migrations

我的解决方案包含:

  • FooBarAsp ,一个asp项目(为应用程序提供UI)
  • FooBar ,一个类库(应用程序)
  • FooBar.Tests ,一个测试项目(测试应用程序)

FooBar使用EF 6 Code First,包含许多模型和DataContext。 FooBarAsp使用Microsoft的Identity框架进行用户身份验证,并且具有ApplicationDbContext。这两种情况都很好,并按预期工作。 Global.asax.cs应该执行MigrateDatabaseToLatestVersion(对吧?)。 FooBar.Tests应该执行DropCreateDatabaseAlways并且不关心迁移(对吧?)。

我应该在FooBarAsp或FooBar中启用Flash吗?对于这两种情况?

在FooBar中运行EnableMigrations后(仅用于踢),我的__MigrationHistory表包含两个InitialCreate行,一个用ContextKey = FooBar.Models.DataContext,另一个用ContextKey = FooBarAsp.Models.ApplicationDbContext。那么他们已经被追踪了吗?如果是这样,(并且由于我没有启用自动迁移),我是否需要在Global.asax.cs中明确运行 MigrateDatabaseToLatestVersion<DataContext>MigrateDatabaseToLatestVersion<ApplicationDbContext>


修改

为什么我不想将ApplicationUser移到FooBar并将ApplicationDbContext合并到DataContext

ASP附带的库存ApplicationUser是一个单独的实体(和单独的ApplicationDbContext,恰好指向同一个数据库)。 ASP的ApplicationUser和身份框架负责身份验证,注册,电子邮件验证,登录,注销,密码,密码强度,密码重置,双因素身份验证,Cookie,会话,来自Facebook等来源的外部登录/ google等.FooBar并不知道或关心其中任何一个。 FooBar的User有一个UserName,ASP的ApplicationUser有一个UserName。当用户登录时,我只需通过UserName查找Foobar的User以及已登录的人。所以当我创建新的Blog时({{1} }是一个FooBar实体),作者是FooBar的Blog(不是User)。最终结果是FooBar不是Web / Desktop / Console / iPhone / Android应用程序。它是一个库,任何这些东西都可以引用,交互并提供用户界面。关键是FooBar没有受到任何这些用户界面的污染或偏见。

所以我不想将ApplicationUser移到FooBar中,因为它来自Microsoft.AspNet.Identity命名空间,而FooBar并不了解或关心ASP.NET(或WPF或任何接口恰好是。)

1 个答案:

答案 0 :(得分:7)

就像John在评论中所说的那样,将所有EF代码移动到一个单独的类库中可能会很好。我通常会为新解决方案创建Web,Domain,DataAccess和Test项目,如果有必要,我们会将其拆分。这为您提供了一些清晰,基本的关注点分离。 Visual Studio Web项目模板不提供,因为它设计为在单个项目中自包含。

Visual Studio的Web模板是小型项目的一个很好的起点,但随着项目的发展,它很快变得一团糟。拥有网站(或多或少是您的表示层),域模型和业务逻辑和数据访问都在同一个项目中并不是特别好的做法。通过在Web应用程序中留下您的用户模型和单独的DbContext来区分它们可能会让IMO更加困惑,特别是如果您的ApplicationUser将参与与您的域类库中的模型的关系。

我建议您将ApplicationUser移到包含域模型的类库中,然后将ApplicationDbContext移到DataAccess类库中。您可以更进一步,将两个DbContexts合并为一个,除非您怀疑项目将变得足够大,需要多个`DbContexts。此时,迁移应该存在的位置变得非常明显。除非你试图将它抽象出去,否则你的初始化程序将总是进入应用程序,在你的情况下是FooBarAsp,所以你要纠正Global.asax是设置它的地方。

然而,如果这对您来说听起来没什么吸引力,并且您希望保持现有的项目结构,那么我认为您最好配置迁移为了一致性,DbContext用于ApplicationDbContext。此时,您的Web项目(FooBarAsp)中有一组迁移,用于继承自IdentityDbContext的{​​{1}}和另一组驻留在类库中的迁移(FooBar) 。两者都需要在您的Web项目的Global.asax.cs中使用初始值设定项。

根据OP的更新进行编辑:我可以看到您希望将ASP.NET相关参考保留在域层之外的地方。如果不将你的用户模型分成两部分,基本上不可能防止这种情况发生。 This is something I asked about when VS2013 was still pre-RTM并且从来没有得到满意的答案,因为它目前不可能拥有一个可以使用不会引入某些与ASP.NET相关的程序集的Identity的用户模型。但是,在某种类似的情况下,DbGeography类型可以是包含在您的域层中的非常有用的类型,但如果不引入与实体框架相关的程序集,则无法使用它。它真正归结为权衡利弊和挑选两个邪恶中较小的一个 - 在你应用设计模式的时间和地点都是务实的。

也就是说,如果您确实要将DbContext与您的网络应用程序中的ApplicationUser分开,我建议从应用程序用户中删除所有无关的字段。事实上,只使用IdentityUser类本身而不是子类化它,因为您将纯粹用于身份验证和授权。但是,我相信您仍然需要为这两种情境启用迁移,并研究如何使用multiple contexts per database with EF6,这在EF5中是不可能的。