[英]ASP.NET Identity with EF Database First MVC5
Is it possible to use the new Asp.net Identity with Database First and EDMX? 是否可以将新的Asp.net标识与Database First和EDMX一起使用? Or only with code first?
或者只使用代码?
Here's what I did: 这是我做的:
1) I made a new MVC5 Project and had the new Identity create the new User and Roles tables in my database. 1)我创建了一个新的MVC5项目并让新的Identity在我的数据库中创建了新的User和Roles表。
2) I then opened my Database First EDMX file and dragged in the new Identity Users table since I have other tables that relate to it. 2)然后我打开了我的Database First EDMX文件并拖入了新的Identity Users表,因为我有其他与之相关的表。
3) Upon saving the EDMX, the Database First POCO generator will auto create a User class. 3)保存EDMX后,Database First POCO生成器将自动创建User类。 However, UserManager and RoleManager expects a User class inheriting from the new Identity namespace (Microsoft.AspNet.Identity.IUser), so using the POCO User class won't work.
但是,UserManager和RoleManager需要从新的Identity命名空间(Microsoft.AspNet.Identity.IUser)继承User类,因此使用POCO User类将不起作用。
I guess a possible solution is to edit my POCO Generation Classes to have my User class inherit from IUser? 我想一个可能的解决方案是编辑我的POCO生成类以使我的User类继承自IUser?
Or is ASP.NET Identity only compatible with Code First Design? 或者ASP.NET Identity仅与Code First Design兼容?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++
Update: Following Anders Abel's suggestion below, this is what I did. 更新:根据Anders Abel的建议,这就是我所做的。 It work's, but I'm wondering if there is a more elegant solution.
它的工作原理,但我想知道是否有更优雅的解决方案。
1) I extended my entity User class by creating a partial class within the same namespace as my auto generated entities. 1)我通过在与自动生成的实体相同的命名空间中创建一个部分类来扩展我的实体User类。
namespace MVC5.DBFirst.Entity
{
public partial class AspNetUser : IdentityUser
{
}
}
2) I changed my DataContext to inherit from IdentityDBContext instead of DBContext. 2)我将DataContext更改为继承IdentityDBContext而不是DBContext。 Note that every time you update your EDMX and regenerate the DBContext and Entity classes, you'll have to set this back to this.
请注意,每次更新EDMX并重新生成DBContext和Entity类时,都必须将其设置为此。
public partial class MVC5Test_DBEntities : IdentityDbContext<AspNetUser> //DbContext
3) Within your auto generated User entity class, you must add the override keyword to the following 4 fields or comment these fields out since they are inherited from IdentityUser (Step 1). 3)在自动生成的User实体类中,必须将override关键字添加到以下4个字段中,或者将这些字段注释掉,因为它们是从IdentityUser继承的(步骤1)。 Note that every time you update your EDMX and regenerate the DBContext and Entity classes, you'll have to set this back to this.
请注意,每次更新EDMX并重新生成DBContext和Entity类时,都必须将其设置为此。
override public string Id { get; set; }
override public string UserName { get; set; }
override public string PasswordHash { get; set; }
override public string SecurityStamp { get; set; }
It should be possible to use the identity system with POCO and Database First, but you'll have to make a couple of tweaks: 应该可以将身份系统与POCO和Database First一起使用,但您必须进行一些调整:
partial
. partial
。 That will make it possible for you to supply additional implementation in a separate file. User
class in another file User
类 partial User : IUser
{
}
That will make the User
class implement the right interface, without touching the actual generated files (editing generated files is always a bad idea). 这将使
User
类实现正确的接口,而不触及实际生成的文件(编辑生成的文件总是一个坏主意)。
My steps are very similar but I wanted to share. 我的步骤非常相似,但我想分享。
1) Create a new MVC5 project 1)创建一个新的MVC5项目
2) Create a new Model.edmx. 2)创建一个新的Model.edmx。 Even if it's a new database and has no tables.
即使它是一个新的数据库,也没有表。
3) Edit web.config and replace this generated connectionstring: 3)编辑web.config并替换生成的connectionstring:
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-SSFInventory-20140521115734.mdf;Initial Catalog=aspnet-SSFInventory-20140521115734;Integrated Security=True" providerName="System.Data.SqlClient" />
with this connectionstring: 使用此连接字符串:
<add name="DefaultConnection" connectionString="Data Source=.\SQLExpress;database=SSFInventory;integrated security=true;" providerName="System.Data.SqlClient" />
Afterwards, build and run the application. 然后,构建并运行应用程序。 Register a user and then the tables will be created.
注册用户,然后将创建表。
EDIT: ASP.NET Identity with EF Database First for MVC5 CodePlex Project Template. 编辑: 使用EF数据库的ASP.NET身份首先用于MVC5 CodePlex项目模板。
I wanted to use an existing database and create relationships with ApplicationUser. 我想使用现有数据库并与ApplicationUser建立关系。 This is how I did it using SQL Server but the same idea would probably work with any DB.
这就是我使用SQL Server的方式,但同样的想法可能适用于任何数据库。
:base("DefaltConnection")
to use your project's DbContext. :base("DefaltConnection")
以使用项目的DbContext。 Edit: Asp.Net Identity Class Diagram 编辑: Asp.Net Identity Class Diagram
IdentityUser
is worthless here because it's the code-first object used by the UserStore
for authentication. IdentityUser
在这里毫无价值,因为它是UserStore
用于身份验证的代码优先对象。 After defining my own User
object, I implemented a partial class that implements IUser
which is used by the UserManager
class. 在定义了我自己的
User
对象之后,我实现了一个实现IUser
的部分类,它由UserManager
类使用。 I wanted my Id
s to be int
instead of string so I just return the UserID's toString(). 我希望我的
Id
是int
而不是string,所以我只返回UserID的toString()。 Similarly I wanted n
in Username
to be uncapitalized. 同样,我希望
Username
n
不被大写。
public partial class User : IUser
{
public string Id
{
get { return this.UserID.ToString(); }
}
public string UserName
{
get
{
return this.Username;
}
set
{
this.Username = value;
}
}
}
You by no means need IUser
. 你绝不需要
IUser
。 It's only an interface used by the UserManager
. 它只是
UserManager
使用的接口。 So if you want to define a different "IUser" you would have to rewrite this class to use your own implementation. 因此,如果要定义不同的“IUser”,则必须重写此类以使用自己的实现。
public class UserManager<TUser> : IDisposable where TUser: IUser
You now write your own UserStore
which handles all of the storage of users, claims, roles, etc. Implement the interfaces of everything that the code-first UserStore
does and change where TUser : IdentityUser
to where TUser : User
where "User" is your entity object 您现在编写自己的
UserStore
来处理用户,声明,角色等的所有存储。实现代码优先UserStore
所做的一切的接口,并将where TUser : IdentityUser
更改到where TUser : User
所在的用户所在的位置实体对象
public class MyUserStore<TUser> : IUserLoginStore<TUser>, IUserClaimStore<TUser>, IUserRoleStore<TUser>, IUserPasswordStore<TUser>, IUserSecurityStampStore<TUser>, IUserStore<TUser>, IDisposable where TUser : User
{
private readonly MyAppEntities _context;
public MyUserStore(MyAppEntities dbContext)
{
_context = dbContext;
}
//Interface definitions
}
Here are a couple examples on some of the interface implementations 以下是一些接口实现的几个示例
async Task IUserStore<TUser>.CreateAsync(TUser user)
{
user.CreatedDate = DateTime.Now;
_context.Users.Add(user);
await _context.SaveChangesAsync();
}
async Task IUserStore<TUser>.DeleteAsync(TUser user)
{
_context.Users.Remove(user);
await _context.SaveChangesAsync();
}
Using the MVC 5 template, I changed the AccountController
to look like this. 使用MVC 5模板,我将
AccountController
更改为如下所示。
public AccountController()
: this(new UserManager<User>(new MyUserStore<User>(new MyAppEntities())))
{
}
Now logging in should work with your own tables. 现在登录应该适用于您自己的表。
Take a look at this project on GitHub: https://github.com/KriaSoft/AspNet.Identity 在GitHub上看看这个项目: https : //github.com/KriaSoft/AspNet.Identity
Which includes: 包括:
Also see : How to create Database-First provider for ADO.NET Identity 另请参阅 : 如何为ADO.NET标识创建数据库优先提供程序
I spent several hours working through this and finally found a solution which I have shared on my blog here . 我花了几个小时通过这个工作,终于找到了,我已经在我的博客共享的解决方案在这里 。 Basically, you need to do everything said in stink 's answer but with one additional thing: ensuring Identity Framework has a specific SQL-Client connection string on top of the Entity Framework connection string used for your application entities.
基本上,你需要做一些在stink的答案中说的话,但还有一件事:确保Identity Framework在用于你的应用程序实体的Entity Framework连接字符串之上有一个特定的SQL-Client连接字符串。
In summary, your application will use a connection string for Identity Framework and another for your application entities. 总之,您的应用程序将使用Identity Framework的连接字符串和您的应用程序实体的另一个字符串。 Each connection string is of a different type.
每个连接字符串都是不同的类型。 Read my blog post for a full tutorial.
阅读我的博客文章,获取完整的教程。
Good question. 好问题。
I'm more of a database-first person. 我更像是数据库第一人。 The code first paradigm seems to loosey-goosey to me, and the "migrations" seem too error prone.
代码第一范式对我来说似乎是松散的,而且“迁移”似乎太容易出错。
I wanted to customize the aspnet identity schema, and not be bothered with migrations. 我想自定义aspnet身份模式,而不是被迁移困扰。 I'm well versed with Visual Studio database projects (sqlpackage, data-dude) and how it does a pretty good job at upgrading schemas.
我非常精通Visual Studio数据库项目(sqlpackage,data-dude)以及它如何在升级模式方面做得非常好。
My simplistic solution is to: 我的简单解决方案是:
1) Create a database project that mirrors the aspnet identity schema 2) use the output of this project (.dacpac) as a project resource 3) deploy the .dacpac when needed 1)创建一个镜像aspnet身份模式的数据库项目2)使用此项目的输出(.dacpac)作为项目资源3)在需要时部署.dacpac
For MVC5, modifying the ApplicationDbContext
class seems to get this going... 对于MVC5,修改
ApplicationDbContext
类似乎可以实现这一目标......
1) Implement IDatabaseInitializer
1)实现
IDatabaseInitializer
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDatabaseInitializer<ApplicationDbContext> { ... }
2) In the constructor, signal that this class will implement database initialization: 2)在构造函数中,表示此类将实现数据库初始化:
Database.SetInitializer<ApplicationDbContext>(this);
3) Implement InitializeDatabase
: 3)实现
InitializeDatabase
:
Here, I chose to use DacFX and deploy my .dacpac 在这里,我选择使用DacFX并部署我的.dacpac
void IDatabaseInitializer<ApplicationDbContext>.InitializeDatabase(ApplicationDbContext context)
{
using (var ms = new MemoryStream(Resources.Binaries.MainSchema))
{
using (var package = DacPackage.Load(ms, DacSchemaModelStorageType.Memory))
{
DacServices services = new DacServices(Database.Connection.ConnectionString);
var options = new DacDeployOptions
{
VerifyDeployment = true,
BackupDatabaseBeforeChanges = true,
BlockOnPossibleDataLoss = false,
CreateNewDatabase = false,
DropIndexesNotInSource = true,
IgnoreComments = true,
};
services.Deploy(package, Database.Connection.Database, true, options);
}
}
}
We have a Entity Model DLL project where we keep our model class. 我们有一个实体模型DLL项目,我们保留我们的模型类。 We also keep a Database Project with all of database scripts.
我们还使用所有数据库脚本保留数据库项目。 My approach was as follows
我的方法如下
1) Create your own project that has the EDMX using database first 1)首先使用数据库创建自己的EDMX项目
2) Script the tables in your db, I used VS2013 connected to localDB (Data Connections) and copied the script to database project, add any custom columns, eg BirthDate [DATE] not null 2)编写数据库中的表,我使用VS2013连接到localDB(数据连接)并将脚本复制到数据库项目,添加任何自定义列,例如BirthDate [DATE] not null
3) Deploy the database 3)部署数据库
4) Update the Model (EDMX) project Add to the Model project 4)更新模型(EDMX)项目添加到模型项目
5) Add any custom columns to the application class 5)将任何自定义列添加到应用程序类
public class ApplicationUser : IdentityUser
{
public DateTime BirthDate { get; set; }
}
In the MVC project AccountController added the following: 在MVC项目中,AccountController添加了以下内容:
The Identity Provider want a SQL Connection String for it to work, to keep only 1 connection string for the database, extract the provider string from EF connection string 身份提供程序需要SQL连接字符串才能工作,只保留数据库的1个连接字符串,从EF连接字符串中提取提供程序字符串
public AccountController()
{
var connection = ConfigurationManager.ConnectionStrings["Entities"];
var entityConnectionString = new EntityConnectionStringBuilder(connection.ConnectionString);
UserManager =
new UserManager<ApplicationUser>(
new UserStore<ApplicationUser>(
new ApplicationDbContext(entityConnectionString.ProviderConnectionString)));
}
I found that @JoshYates1980 does have the simplest answer. 我发现@JoshYates1980确实有最简单的答案。
After a series trials and errors I did what Josh suggested and replaced the connectionString
with my generated DB connection string. 经过一系列的试验和错误后,我做了Josh建议的事情,并用我生成的数据库连接字符串替换了
connectionString
。 what I was confused about originally was the following post: 我最初感到困惑的是以下帖子:
How to add ASP.NET MVC5 Identity Authentication to existing database 如何将ASP.NET MVC5身份验证添加到现有数据库
Where the accepted answer from @Win stated to change the ApplicationDbContext()
connection name. 来自@Win的接受答案声明要更改
ApplicationDbContext()
连接名称。 This is a little vague if you are using Entity and a Database/Model first approach where the database connection string is generated and added to the Web.config
file. 如果您使用Entity和数据库/模型第一种方法生成数据库连接字符串并将其添加到
Web.config
文件,则这有点模糊。
The ApplicationDbContext()
connection name is mapped to the default connection in the Web.config
file. ApplicationDbContext()
连接名称映射到Web.config
文件中的默认连接。 Therefore, Josh's method works best, but to make the ApplicationDbContext()
more readable I would suggest changing the name to your database name as @Win originally posted, making sure to change the connectionString
for the "DefaultConnection" in the Web.config
and comment out and/or remov the Entity generated database include. 因此,Josh的方法效果最好,但为了使
ApplicationDbContext()
更具可读性,我建议将名称更改为@Win最初发布的数据库名称,确保更改Web.config
的“DefaultConnection”的connectionString
并注释out和/或删除实体生成的数据库包括。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.