问题描述
我的解决方案包含:
- FooBarAsp ,一个asp项目(为应用程序提供一个UI) / li>
- FooBar ,一个类库(应用程序)
- FooBar.Tests 项目(测试应用程序)
- FooBarAsp, an asp project (provides a UI for the application)
- FooBar, a class library (the application)
- FooBar.Tests, a test project (tests the application)
FooBar使用EF 6代码优先,并包含多个模型,并且 DataContext的
。 FooBarAsp使用Microsoft的Identity框架进行用户身份验证,并具有一个 ApplicationDbContext
。这两种情境都会发挥出色,按预期工作。 Global.asax.cs应执行 MigrateDatabaseToLatestVersion
(对?)。 FooBar.Tests应该执行 DropCreateDatabaseAlways
,而不会关心迁移(对吗?)。
FooBar uses EF 6 Code First, and contains a number of models, and a DataContext
. FooBarAsp uses Microsoft's Identity framework for user authentication, and has an ApplicationDbContext
. Both contexts play nice and work as expected. Global.asax.cs should execute MigrateDatabaseToLatestVersion
(right?). FooBar.Tests should execute DropCreateDatabaseAlways
and won't care about migrations (right?).
应该我在FooBarAsp或FooBar中启用移动?对于两个上下文?
在FooBar中运行EnableMigrations(仅用于踢)后,我的__MigrationHistory表包含两个InitialCreate行,一个具有ContextKey = FooBar.Models。 DataContext,另一个与ContextKey = FooBarAsp.Models.ApplicationDbContext。所以他们都被跟踪了?如果是这样(因为我没有启用自动迁移),那么我需要显式地运行 MigrateDatabaseToLatestVersion< DataContext>
和
After running EnableMigrations in FooBar (just for kicks), my __MigrationHistory table contains two InitialCreate rows, one with ContextKey=FooBar.Models.DataContext and the other with ContextKey=FooBarAsp.Models.ApplicationDbContext. So they're both being tracked already? If so, (and since I did not enable automatic migrations), do I need to explicitly run both MigrateDatabaseToLatestVersion<DataContext>
and MigrateDatabaseToLatestVersion<ApplicationDbContext>
in Global.asax.cs?
为什么我不想将 ApplicationUser
移动到FooBar中并合并 ApplicationDbContext
into
DataContext
?
Why don't I want to move ApplicationUser
into FooBar and merge ApplicationDbContext
into DataContext
?
股票 ApplicationUser
ASP附带的是一个单独的实体(和单独的 ApplicationDbContext
,恰好指向同一个数据库)。 ASP的 ApplicationUser
和身份框架负责认证,注册,电子邮件验证,登录,注销,密码,密码强度,密码重置,双因素身份验证,Cookie,会话,外部从Facebook /谷歌等资源登录。FooBar不知道或关心任何一个。 FooBar的用户
有一个UserName,ASP的 ApplicationUser
有一个UserName。当用户登录时,我只是用UserName查找Foobar的 User
,那是谁登录了,所以当我创建一个新的 Blog
(其中 Blog
是一个FooBar实体),作者是FooBar的用户
(不是 ApplicationUser
)。最终的结果是,FooBar不是Web / Desktop / Console / iPhone / Android应用程序。这是一个图书馆,任何这些东西都可以引用,交互和提供用户界面。关键是FooBar没有受到任何这些用户界面的污染或偏见。
The stock ApplicationUser
that comes with ASP is a separate entity (and separate ApplicationDbContext
, which happens to point to the same database). ASP's ApplicationUser
and the Identity framework take care of authentication, registration, email verification, login, logout, passwords, password strength, passwords resetting, two factor authentication, cookies, sessions, external login from sources like facebook/google, etc. FooBar doesn't know or care about any of that. FooBar's User
s have a UserName, and ASP's ApplicationUser
s have a UserName. When a user logs in, I just look up Foobar's User
by UserName, and that's who is logged in. So when I create a new Blog
(where Blog
is a FooBar entity), the author is FooBar's User
(not ApplicationUser
). The end result is that FooBar is not a Web/Desktop/Console/iPhone/Android application. It's a library that any of those things can reference, interact with, and provide a user interface for. The point is that FooBar is not polluted or biased by any of those user interfaces.
所以我不想移动 ApplicationUser
进入FooBar,因为它来自Microsoft.AspNet.Identity命名空间,而FooBar不知道或关心ASP.NET(或WPF或任何界面恰好是)。
So I don't want to move ApplicationUser
into FooBar because it's from the Microsoft.AspNet.Identity namespace, and FooBar doesn't know or care about ASP.NET (or WPF or whatever the interface happens to be).
推荐答案
像约翰在评论中说的那样,你可以将所有的EF代码移动到一个单独的类库中。我通常会创建一个新的解决方案的Web,Domain,DataAccess和Test项目,如果有必要,将其分解成更多的路径。这给你一些明确的,基本的关切分离。 Visual Studio Web项目模板没有提供,因为它被设计为在单个项目中自包含。
Like John said in his comment, you might be served well by moving all of your EF code into a separate class library. I typically create Web, Domain, DataAccess, and Test projects for a new solutions, and split them up even more down the road if it's necessary. This gives you some clear, basic separation of concerns up front. The Visual Studio Web project templates don't provide that, as it's designed to be self-contained in a single project.
Visual Studio的Web模板是一个很好的起点小项目,但随着项目的增长,它很快就变得混乱了。拥有网站(或多或少是您的表现层),域模型和业务逻辑和数据访问都在同一个项目中并不是特别好的做法。在Web应用程序中留下您的用户模型和单独的 DbContext
部分分离它们可能会更加混乱的IMO,特别是如果您的 ApplicationUser
将参与与域类库中的模型的关系。
Visual Studio's Web template is a good starting point for small projects but it pretty quickly becomes a mess as the project grows. Having the website (which is more or less your presentation layer), domain models & business logic, and data access all in the same project isn't particularly good practice. Partially separating them by leaving your user models and a separate DbContext
behind in the web application can be even more confusing IMO, especially if your ApplicationUser
s are going to participate in relationships with models from your domain class library.
我建议将您的 ApplicationUser
移动到包含您的域模型的类库中,并将您的 ApplicationDbContext
并将其移动到DataAccess类库中。您可以进一步,将您的两个DbContexts组合成一个没有太多的努力,除非你怀疑项目将增长到足以需要多个`DbContexts。在这一点上,你的移民应该生活在哪里。除非你试图抽象出来,否则你的Initializer会永远在应用程序中,在你的情况下,它是FooBarAsp,所以你是正确的,Global.asax是设置的地方。
I would suggest moving your ApplicationUser
into the class library that contains your domain models, and take your ApplicationDbContext
and move it into a DataAccess class library. You can take that one step further and combine your two DbContexts into one without much effort, unless you suspect that the project will grow large enough to require multiple `DbContexts. At that point, it becomes very apparent where your Migrations should live. Unless you're trying to abstract it away, your Initializer will always go in the application, which in your case is FooBarAsp, so you're correct that Global.asax is the place to set that up.
但是,如果这听起来对您没有吸引力,而您希望保持项目结构的目前状态,那么我认为您最好配置迁移为了一致性,都要求 DbContext
。在这一点上,您将在 ApplicationDbContext
中继承自 IdentityDbContext $ c $的Web项目(FooBarAsp)中的一组迁移c>和另一组位于你的类库(FooBar)中的迁移。两者都将需要您的Web项目的Global.asax.cs中的初始化器。
However, if this sounds unappealing to you and you'd like to keep your project structure as it currently is, it's my opinion that you would be best off configuring migrations for both DbContext
s for consistency's sake. At that point, You'd have a set of Migrations in your web project (FooBarAsp) for the ApplicationDbContext
that inherits from IdentityDbContext
and another set of migrations that resided in your class library (FooBar). Both would need initializers in the Global.asax.cs of your web project.
根据OP更新编辑:我可以看到你在哪里来自您希望将ASP.NET相关引用保留在您的域层之外。基本上不可能保持这种情况,而不会像您完成的那样将用户模型分成两部分。 ,从来没有得到一个令人满意的答案,因为目前不可能有一个用户模型与Identity不兼容的ASP.NET相关程序集。然而,在某种类似的情况下, DbGeography
类型可能是一个非常有用的类型,可以包含在您的域层中,但不可能使用它而不会拉入Entity Framework相关的程序集。这真的归功于权衡利弊,挑选两个罪恶中的较小者 - 在你应用设计模式的时候和地点是务实的。
Edit based on OP's update: I can see where you're coming from in your desire to keep ASP.NET related references out of your domain layer. It's basically impossible to keep this from happening without splitting up your user models in two as you've done. This is something I asked about when VS2013 was still pre-RTM and never got a satisfactory answer because it's currently not possible to have an User model that works with Identity that doesn't pull in some ASP.NET related assemblies. However, in a somewhat analogous situation, the DbGeography
type can be a very useful type to include in your domain layer, but it's impossible to use it without pulling in Entity Framework related assemblies. It really comes down to weighing the pros and cons and picking the lesser of two evils- be pragmatic in when and where you apply design patterns.
说,如果你做想要保持 DbContext
在您的Web应用程序中单独使用 ApplicationUser
,我建议拔出所有无关的事实上,应用程序用户的字段实际上只使用IdentityUser类本身,而不是将其子类化,因为您将纯粹用于身份验证和授权。但是,我相信您仍然需要为这两个上下文启用迁移,并查看如何使用,这在EF5中是不可能的。
That said, if you do want to keep the DbContext
s separate and the ApplicationUser
in your web application, I'd suggest pulling out all the extraneous fields from the application user- in fact, just use the IdentityUser class itself instead of subclassing it since you'll be using it purely for authentication and authorization. However, I believe you'll still need to enable Migrations for both contexts and look into how to use multiple contexts per database with EF6, which wasn't possible in EF5.
这篇关于EF迁移应该在哪里,我的Class Library项目或ASP.NET项目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!