使用EF Database First MVC5的ASP.NET标识

时间:2013-11-12 21:13:27

标签: asp.net asp.net-mvc asp.net-mvc-5 ef-database-first asp.net-identity

是否可以在Database First和EDMX中使用新的Asp.net标识?或者只使用代码?

这就是我的所作所为:

1)我制作了一个新的MVC5项目并让新的Identity在我的数据库中创建了新的User和Roles表。

2)然后我打开了我的Database First EDMX文件并拖入了新的Identity Users表,因为我有其他与之相关的表。

3)保存EDMX后,Database First POCO生成器将自动创建User类。但是,UserManager和RoleManager期望从新的Identity命名空间(Microsoft.AspNet.Identity.IUser)继承User类,因此使用POCO User类将不起作用。

我想一个可能的解决方案是编辑我的POCO生成类以使我的User类继承自IUser?

或者ASP.NET Identity仅与Code First Design兼容吗?

+++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++

更新:根据Anders Abel的建议,这就是我所做的。它有用,但我想知道是否有更优雅的解决方案。

1)我通过在与自动生成的实体相同的命名空间中创建一个部分类来扩展我的实体User类。

namespace MVC5.DBFirst.Entity
{
    public partial class AspNetUser : IdentityUser
    {
    }
}

2)我将DataContext更改为继承IdentityDBContext而不是DBContext。请注意,每次更新EDMX并重新生成DBContext和Entity类时,都必须将其设置为此。

 public partial class MVC5Test_DBEntities : IdentityDbContext<AspNetUser>  //DbContext

3)在自动生成的User实体类中,必须将override关键字添加到以下4个字段中,或者将这些字段注释掉,因为它们是从IdentityUser继承的(步骤1)。请注意,每次更新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; }

9 个答案:

答案 0 :(得分:16)

应该可以将身份系统与POCO和Database First一起使用,但你必须做一些调整:

  1. 更新用于POCO生成的.tt文件以生成实体类partial。这将使您可以在单独的文件中提供其他实现。
  2. 在另一个文件中部分实现User
  3. partial User : IUser
    {
    }
    

    这将使User类实现正确的接口,而不触及实际生成的文件(编辑生成的文件总是一个坏主意)。

答案 1 :(得分:13)

我的步骤非常相似,但我想分享。

1)创建一个新的MVC5项目

2)创建一个新的Model.edmx。即使它是一个新的数据库而且没有表格。

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" />

使用此连接字符串:

<add name="DefaultConnection" connectionString="Data Source=.\SQLExpress;database=SSFInventory;integrated security=true;" providerName="System.Data.SqlClient" />

然后,构建并运行应用程序。注册用户,然后将创建表。

答案 2 :(得分:10)

编辑: ASP.NET Identity with EF Database First for MVC5 CodePlex Project Template.


我想使用现有数据库并与ApplicationUser建立关系。这就是我使用SQL Server的方式,但同样的想法可能适用于任何数据库。

  1. 创建MVC项目
  2. 打开Web.config中DefaultConnection下列出的数据库。它将被调用(aspnet- [timestamp]或类似的东西。)
  3. 编写数据库表的脚本。
  4. 将脚本表插入SQL Server Management Studio中的现有数据库。
  5. 自定义并添加与 ApplicationUser 的关系(如有必要)。
  6. 创建新的Web项目&gt; MVC&gt; DB First Project&gt;使用EF导入数据库...排除您插入的标识类。
  7. IdentityModels.cs 中,更改ApplicationDbContext :base("DefaltConnection")以使用项目的DbContext。

  8. 编辑: Asp.Net Identity Class Diagram enter image description here

答案 3 :(得分:8)

IdentityUser在这里毫无价值,因为它是UserStore用于身份验证的代码优先对象。在定义了我自己的User对象之后,我实现了一个实现IUser类的UserManager的部分类。我希望我的Id s为int而不是字符串,所以我只返回UserID的toString()。同样,我希望n中的Username无法投入资金。

public partial class User : IUser
{

    public string Id
    {
        get { return this.UserID.ToString(); }
    }

    public string UserName
    {
        get
        {
            return this.Username;
        }
        set
        {
            this.Username = value;
        }
    }
}

您无需IUser。它只是UserManager使用的界面。因此,如果要定义不同的“IUser”,则必须重写此类以使用自己的实现。

public class UserManager<TUser> : IDisposable where TUser: IUser

您现在编写自己的UserStore来处理用户,声明,角色等的所有存储。实现代码优先UserStore所做的所有事情的接口并更改{{1} } 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
}

使用MVC 5模板,我将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(); } 更改为如下所示。

AccountController

现在登录应该适用于您自己的表。

答案 4 :(得分:3)

在GitHub上查看这个项目: https://github.com/KriaSoft/AspNet.Identity

其中包括:

  • ASP.NET Identity 2.0的SQL数据库项目模板
  • 实体框架数据库 - 第一个提供商
  • 源代码和示例

enter image description here

另见How to create Database-First provider for ADO.NET Identity

答案 5 :(得分:2)

我花了几个小时来完成这项工作,最后找到了一个我在博客here上分享的解决方案。基本上,您需要在stink的答案中执行所有操作,但还需要做一件事:确保Identity Framework在用于应用程序实体的Entity Framework连接字符串之上具有特定的SQL-Client连接字符串

总之,您的应用程序将使用Identity Framework的连接字符串和您的应用程序实体的另一个字符串。每个连接字符串都是不同的类型。阅读我的博客文章,获取完整的教程。

答案 6 :(得分:2)

好问题。

我更像是数据库第一人。代码第一范式似乎对我来说是松散的,并且#34;迁移&#34;似乎太容易出错了。

我想自定义aspnet身份架构,而不是被迁移困扰。我非常精通Visual Studio数据库项目(sqlpackage,data-dude)以及它在升级模式方面做得非常好。

我的简单解决方案是:

1)创建一个镜像aspnet身份模式的数据库项目 2)使用此项目的输出(.dacpac)作为项目资源 3)在需要时部署.dacpac

对于MVC5,修改ApplicationDbContext类似乎就是这样......

1)实施IDatabaseInitializer

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDatabaseInitializer<ApplicationDbContext> { ... }

2)在构造函数中,表示此类将实现数据库初始化:

Database.SetInitializer<ApplicationDbContext>(this);

3)实施InitializeDatabase

在这里,我选择使用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);
            }
        }
    }

答案 7 :(得分:1)

我们有一个实体模型DLL项目,我们保留我们的模型类。我们还使用所有数据库脚本保留数据库项目。我的方法如下

1)首先使用数据库创建自己的EDMX项目

2)编写数据库中的表,我使用VS2013连接到localDB(数据连接)并将脚本复制到数据库项目,添加任何自定义列,例如BirthDate [日期]不为空

3)部署数据库

4)更新模型(EDMX)项目添加到模型项目

5)将任何自定义列添加到应用程序类

public class ApplicationUser : IdentityUser
{
    public DateTime BirthDate { get; set; }
}

在MVC项目中,AccountController添加了以下内容:

Identity Provider需要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)));
}

答案 8 :(得分:1)

我发现@JoshYates1980确实有最简单的答案。

经过一系列的试验和错误后,我做了Josh建议的事情,并用我生成的数据库连接字符串替换了connectionString。我最初感到困惑的是以下帖子:

How to add ASP.NET MVC5 Identity Authentication to existing database

@Win接受的答案声明要更改ApplicationDbContext()连接名称。如果您使用实体和数据库/模型第一种方法来生成数据库连接字符串并将其添加到Web.config文件,则这有点模糊。

ApplicationDbContext()连接名称​​已映射Web.config文件中的默认连接。因此,Josh的方法效果最好,但为了使ApplicationDbContext()更具可读性,我建议将名称更改为@Win最初发布的数据库名称,确保更改{Default}的“{1}}” connectionString并注释和/或删除实体生成的数据库包括。

Code Examples: