88

是否可以将新的 Asp.net Identity 与 Database First 和 EDMX 一起使用?还是只有代码优先?

这是我所做的:

1)我创建了一个新的 MVC5 项目,并让新的身份在我的数据库中创建新的用户和角色表。

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

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

我想一个可能的解决方案是编辑我的 POCO 生成类以让我的用户类从 IUser 继承?

还是 ASP.NET 标识仅与代码优先设计兼容?

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

更新:按照安德斯·阿贝尔的建议,这就是我所做的。它有效,但我想知道是否有更优雅的解决方案。

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

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)在您自动生成的用户实体类中,您必须将 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; }
4

9 回答 9

16

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

  1. 更新 .tt 文件以生成 POCO 以生成实体类partial。这将使您可以在单独的文件中提供额外的实现。
  2. User在另一个文件中对类进行部分实现

 

partial User : IUser
{
}

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

于 2013-11-12T21:30:09.563 回答
13

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

1)新建一个MVC5项目

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

3) 编辑 web.config 并替换这个生成的连接字符串:

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

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

于 2014-05-21T17:48:36.130 回答
10

编辑: ASP.NET Identity with EF Database First for MVC5 CodePlex 项目模板。


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

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

编辑:Asp.Net 身份类图 在此处输入图像描述

于 2013-11-12T21:49:10.930 回答
8

IdentityUser在这里毫无价值,因为它是UserStore用于身份验证的代码优先对象。在定义我自己的User对象之后,我实现了一个部分类,该类实现了该类IUser使用的UserManager。我希望我Id的 sint代替字符串,所以我只返回 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并更改where TUser : IdentityUserwhere 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
}

以下是一些接口实现的几个示例

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();
}

使用 MVC 5 模板,我将其更改AccountController为如下所示。

public AccountController()
        : this(new UserManager<User>(new MyUserStore<User>(new MyAppEntities())))
{
}

现在登录应该可以使用您自己的表。

于 2014-01-14T20:02:27.663 回答
3

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

包括:

  • ASP.NET Identity 2.0 的 SQL 数据库项目模板
  • 实体框架数据库优先提供者
  • 源代码和示例

在此处输入图像描述

另请参阅如何为 ADO.NET 身份创建数据库优先提供程序

于 2014-04-13T08:59:54.180 回答
3

好问题。

我更像是一个数据库第一的人。代码第一范式对我来说似乎很松散,而且“迁移”似乎太容易出错。

我想自定义 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);
            }
        }
    }
于 2015-09-17T04:47:06.483 回答
2

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

总之,您的应用程序将为身份框架使用一个连接字符串,为您的应用程序实体使用另一个连接字符串。每个连接字符串属于不同的类型。阅读我的博客文章以获得完整的教程。

于 2014-05-20T19:03:01.583 回答
2

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

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

如何将 ASP.NET MVC5 身份验证添加到现有数据库

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

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

代码示例:

于 2017-03-09T05:15:26.867 回答
1

我们有一个实体模型 DLL 项目,我们在其中保存我们的模型类。我们还保留一个包含所有数据库脚本的数据库项目。我的方法如下

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

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

3) 部署数据库

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

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

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

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

身份提供者需要一个 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)));
}
于 2014-04-06T15:45:13.677 回答