Identidade ASP.NET com o database EF First MVC5

É possível usar o novo Asp.net Identity com database primeiro e EDMX? Ou apenas com o código primeiro?

Aqui está o que eu fiz:

1) Eu fiz um novo projeto MVC5 e tive a nova identidade criar as novas tabelas de usuário e funções no meu database.

2) Em seguida, abri meu database EDMX primeiro arquivo e arrastou a nova tabela de usuários de identidade desde que eu tenho outras tabelas que se relacionam com ele.

3) Ao salvar o EDMX, o gerador POCO do database primeiro criará automaticamente uma class de usuário. No entanto, o UserManager e o RoleManager esperam que uma class User herde do novo namespace Identity (Microsoft.AspNet.Identity.IUser), portanto, o uso da class POCO User não funcionará.

Eu acho que uma solução possível é editar minhas classs de geração POCO para ter minha class de usuário herdar de IUser?

Ou o ASP.NET Identity é compatível apenas com o Code First Design?

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

Atualização: Seguindo a sugestão de Anders Abel abaixo, foi o que fiz. Isso funciona, mas eu estou querendo saber se existe uma solução mais elegante.

1) Eu estendi minha class User de entidade criando uma class parcial dentro do mesmo namespace que minhas entidades geradas automaticamente.

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

2) Eu mudei meu DataContext para herdar de IdentityDBContext em vez de DBContext. Note que toda vez que você atualiza seu EDMX e regenera as classs DBContext e Entity, você terá que definir isso de volta para isto.

  public partial class MVC5Test_DBEntities : IdentityDbContext //DbContext 

3) Em sua class de entidade User gerada automaticamente, você deve include a palavra-chave override nos quatro campos a seguir ou comentar esses campos, já que eles são herdados do IdentityUser (Etapa 1). Note que toda vez que você atualiza seu EDMX e regenera as classs DBContext e Entity, você terá que definir isso de volta para isto.

  override public string Id { get; set; } override public string UserName { get; set; } override public string PasswordHash { get; set; } override public string SecurityStamp { get; set; } 

Deve ser possível usar o sistema de identidade com POCO e Database First, mas você terá que fazer alguns ajustes:

  1. Atualize o arquivo .tt para geração de POCO para tornar as classs de entidade partial . Isso possibilitará que você forneça implementação adicional em um arquivo separado.
  2. Fazer uma implementação parcial da class User em outro arquivo
 partial User : IUser { } 

Isso fará com que a class User implemente a interface correta, sem tocar nos arquivos gerados (a edição de arquivos gerados é sempre uma má idéia).

Meus passos são muito parecidos, mas eu queria compartilhar.

1) Crie um novo projeto MVC5

2) Crie um novo Model.edmx. Mesmo que seja um novo database e não tenha tabelas.

3) Edite web.config e substitua esta cadeia de conexões gerada:

  

com esta conexão:

  

Depois, construa e execute o aplicativo. Registre um usuário e, em seguida, as tabelas serão criadas.

EDIT: Identidade ASP.NET com o database EF primeiro para o modelo de projeto MVC5 CodePlex.


Eu queria usar um database existente e criar relacionamentos com o ApplicationUser. Foi assim que fiz isso usando o SQL Server, mas a mesma ideia provavelmente funcionaria com qualquer database.

  1. Crie um projeto MVC
  2. Abra o BD listado sob o DefaultConnection no Web.config. Ele será chamado (aspnet- [timestamp] ou algo assim).
  3. Script as tabelas do database.
  4. Insira as tabelas com script no database existente no SQL Server Management Studio.
  5. Personalize e adicione relacionamentos ao ApplicationUser (se necessário).
  6. Crie um novo projeto da Web> MVC> DB First Project> Importar database com EF … Excluindo as classs de identidade inseridas.
  7. Em IdentityModels.cs, altere o ApplicationDbContext :base("DefaltConnection") para usar o :base("DefaltConnection") seu projeto.

Editar: Diagrama de class de identidade Asp.Net insira a descrição da imagem aqui

IdentityUser é inútil aqui porque é o primeiro object de código usado pela UserStore para autenticação. Depois de definir o meu próprio object User , eu implementei uma class partial que implementa o IUser que é usado pela class UserManager . Eu queria que meus Id s fossem int vez de string, então eu retornei o toString () do UserID. Da mesma forma, eu queria que n em Username de Username fosse não capitalizado.

 public partial class User : IUser { public string Id { get { return this.UserID.ToString(); } } public string UserName { get { return this.Username; } set { this.Username = value; } } } 

Você não precisa de IUser . É apenas uma interface usada pelo UserManager . Portanto, se você quiser definir um “IUser” diferente, precisará rewrite essa class para usar sua própria implementação.

 public class UserManager : IDisposable where TUser: IUser 

Agora você escreve sua própria UserStore que lida com todo o armazenamento de usuários, reclamações, papéis, etc. Implemente as interfaces de tudo que o primeiro UserStore código faz e mude where TUser : IdentityUser para where TUser : User onde “User” é seu object de entidade

 public class MyUserStore : IUserLoginStore, IUserClaimStore, IUserRoleStore, IUserPasswordStore, IUserSecurityStampStore, IUserStore, IDisposable where TUser : User { private readonly MyAppEntities _context; public MyUserStore(MyAppEntities dbContext) { _context = dbContext; } //Interface definitions } 

Aqui estão alguns exemplos de algumas implementações de interface

 async Task IUserStore.CreateAsync(TUser user) { user.CreatedDate = DateTime.Now; _context.Users.Add(user); await _context.SaveChangesAsync(); } async Task IUserStore.DeleteAsync(TUser user) { _context.Users.Remove(user); await _context.SaveChangesAsync(); } 

Usando o modelo MVC 5, mudei o AccountController para ficar assim.

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

Agora, o login deve funcionar com suas próprias tabelas.

Dê uma olhada neste projeto no GitHub: https://github.com/KriaSoft/AspNet.Identity

Que inclui:

  • Modelo de projeto de database SQL para o ASP.NET Identity 2.0
  • Banco de Dados do Entity Framework – Primeiro Provedor (es)
  • Código Fonte e Amostras

insira a descrição da imagem aqui

Veja também : Como criar um provedor de primeiro database para o ADO.NET Identity

Passei várias horas trabalhando nisso e finalmente encontrei uma solução que compartilhei no meu blog aqui . Basicamente, você precisa fazer tudo o que foi dito na resposta do fedor , mas com uma coisa adicional: garantir que o Identity Framework tenha uma cadeia de conexão SQL-Client específica na cadeia de conexão do Entity Framework usada para suas entidades de aplicativo.

Em resumo, seu aplicativo usará uma string de conexão para o Identity Framework e outra para suas entidades de aplicativo. Cada string de conexão é de um tipo diferente. Leia minha postagem no blog para um tutorial completo.

Boa pergunta.

Eu sou mais de uma primeira pessoa de database. O primeiro paradigma do código parece me perder, e as “migrações” parecem muito propensas a erros.

Eu queria personalizar o esquema de identidade do aspnet e não ser incomodado com migrações. Eu sou bem versado com projetos de database do Visual Studio (sqlpackage, data-dude) e como ele faz um bom trabalho na atualização de esquemas.

Minha solução simplista é:

1) Crie um projeto de database que espelhe o esquema de identidade do aspnet 2) use a saída deste projeto (.dacpac) como um recurso do projeto 3) implante o .dacpac quando necessário

Para o MVC5, modificar a class ApplicationDbContext parece dar um jeito nisso …

1) Implementar IDatabaseInitializer

public class ApplicationDbContext : IdentityDbContext, IDatabaseInitializer { ... }

2) No construtor, sinalize que esta class implementará a boot do database:

Database.SetInitializer(this);

3) Implemente InitializeDatabase :

Aqui, optei por usar o DacFX e implantar meu .dacpac

  void IDatabaseInitializer.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); } } } 

Temos um projeto de DLL de modelo de entidade onde mantemos nossa class de modelo. Também mantemos um projeto de database com todos os scripts de database. Minha abordagem foi a seguinte

1) Crie seu próprio projeto que tenha o EDMX usando o database primeiro

2) Script as tabelas em seu database, eu usei VS2013 conectado ao localDB (conexões de dados) e copiei o script para projeto de database, adicione quaisquer colunas personalizadas, por exemplo, DataDeNascimento [DATA] não null

3) Implantar o database

4) Atualizar o projeto do modelo (EDMX) Adicionar ao projeto do modelo

5) Adicione quaisquer colunas personalizadas à class do aplicativo

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

No projeto MVC AccountController adicionou o seguinte:

O provedor de identidade deseja que uma cadeia de conexão SQL funcione, para manter apenas uma cadeia de conexão para o database, extraia a cadeia de caracteres do provedor da cadeia de conexão EF

 public AccountController() { var connection = ConfigurationManager.ConnectionStrings["Entities"]; var entityConnectionString = new EntityConnectionStringBuilder(connection.ConnectionString); UserManager = new UserManager( new UserStore( new ApplicationDbContext(entityConnectionString.ProviderConnectionString))); } 

Eu descobri que @ JoshYates1980 tem a resposta mais simples.

Depois de uma série de tentativas e erros, fiz o que Josh sugeriu e substituí o connectionString pela minha string de conexão de database gerada. o que eu estava confuso sobre originalmente era o seguinte post:

Como adicionar a autenticação de identidade da ASP.NET MVC5 ao database existente

Onde a resposta aceita de @Win afirmou para alterar o nome da conexão ApplicationDbContext() . Isso é um pouco vago se você estiver usando Entity e uma primeira abordagem de Database / Model em que a cadeia de conexão do database é gerada e adicionada ao arquivo Web.config .

O nome da conexão ApplicationDbContext() é mapeado para a conexão padrão no arquivo Web.config . Portanto, o método de Josh funciona melhor, mas para tornar o ApplicationDbContext() mais legível, sugiro alterar o nome do database como @Win originalmente postado, certificando-se de alterar o connectionString para o “DefaultConnection” no Web.config e comentar e / ou remova o database gerado pela Entidade.

Exemplos de código: