Est-il possible d'utiliser la nouvelle identité Asp.net avec Database First et EDMX? Ou seulement avec le code en premier?
Voici ce que j'ai fait:
1) J'ai créé un nouveau projet MVC5 et la nouvelle identité a créé les nouvelles tables d'utilisateurs et de rôles dans ma base de données.
2) J'ai ensuite ouvert mon fichier EDMX de base de données d'abord et je l'ai glissé dans le nouveau tableau Utilisateurs d'identité, car j'ai d'autres tableaux qui s'y rapportent.
3) Lors de la sauvegarde de l’EDMX, le générateur de POCO Database First créera automatiquement une classe d’utilisateur. Cependant, UserManager et RoleManager attendent une classe User héritant du nouvel espace de noms Identity (Microsoft.AspNet.Identity.IUser), de sorte que l'utilisation de la classe POCO User ne fonctionnera pas.
Je suppose qu'une solution possible consiste à éditer mes classes de génération POCO pour que ma classe d'utilisateurs hérite de IUser?
Ou bien ASP.NET Identity est-il uniquement compatible avec Code First Design?
++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++
Mise à jour: À la suite de la suggestion d'Anders Abel ci-dessous, voici ce que j'ai fait. Cela fonctionne, mais je me demande s’il existe une solution plus élégante.
1) J'ai étendu ma classe d'utilisateurs entity en créant une classe partielle dans le même espace de noms que mes entités générées automatiquement.
namespace MVC5.DBFirst.Entity
{
public partial class AspNetUser : IdentityUser
{
}
}
2) J'ai changé mon DataContext pour hériter d'IdentityDBContext au lieu de DBContext. Notez que chaque fois que vous mettez à jour votre EDMX et régénérez les classes DBContext et Entity, vous devez le redéfinir sur ceci.
public partial class MVC5Test_DBEntities : IdentityDbContext<AspNetUser> //DbContext
3) Au sein de votre classe d'entité utilisateur générée automatiquement, vous devez ajouter le mot-clé override aux 4 champs suivants ou commenter ces champs car ils sont hérités d'IdentityUser (étape 1). Notez que chaque fois que vous mettez à jour votre EDMX et régénérez les classes DBContext et Entity, vous devez le redéfinir sur ceci.
override public string Id { get; set; }
override public string UserName { get; set; }
override public string PasswordHash { get; set; }
override public string SecurityStamp { get; set; }
Il devrait être possible d'utiliser le système d'identité avec POCO et Database First, mais vous devrez faire quelques ajustements:
partial
. Cela vous permettra de fournir une implémentation supplémentaire dans un fichier séparé.User
dans un autre fichierpartial User : IUser
{
}
Cela fera que la classe User
implémentera la bonne interface, sans toucher aux fichiers générés (éditer des fichiers générés est toujours une mauvaise idée).
Mes pas sont très similaires mais je voulais partager.
1) Créer un nouveau projet MVC5
2) Créez un nouveau Model.edmx. Même si c'est une nouvelle base de données et n'a pas de tables.
3) Editez web.config et remplacez cette chaîne de connexion générée:
<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" />
avec cette connectionstring:
<add name="DefaultConnection" connectionString="Data Source=.\SQLExpress;database=SSFInventory;integrated security=true;" providerName="System.Data.SqlClient" />
Ensuite, générez et exécutez l'application. Enregistrez un utilisateur et les tables seront créées.
EDIT: Identité ASP.NET avec la base de données EF en premier pour le modèle de projet MVC5 CodePlex.
Je voulais utiliser une base de données existante et créer des relations avec ApplicationUser. Voici comment je l'ai fait avec SQL Server, mais la même idée fonctionnerait probablement avec n'importe quelle base de données.
:base("DefaltConnection")
pour utiliser le DbContext de votre projet.Edit: Diagramme de classe d’identité Asp.Net
IdentityUser
ne vaut rien ici car c'est le premier objet de code utilisé par le UserStore
pour l'authentification. Après avoir défini mon propre objet User
, j'ai implémenté une classe partielle qui implémente IUser
qui est utilisée par la classe UserManager
. Je voulais que mon Id
s soit int
à la place de chaîne, aussi je ne retourne que l'ID utilisateur toString (). De même, je souhaitais que n
dans Username
ne soit pas capitalisé.
public partial class User : IUser
{
public string Id
{
get { return this.UserID.ToString(); }
}
public string UserName
{
get
{
return this.Username;
}
set
{
this.Username = value;
}
}
}
Vous n'avez nullement besoin de IUser
. Ce n'est qu'une interface utilisée par UserManager
. Donc, si vous voulez définir un "IUser" différent, vous devrez réécrire cette classe pour utiliser votre propre implémentation.
public class UserManager<TUser> : IDisposable where TUser: IUser
Vous écrivez maintenant votre propre UserStore
qui gère tout le stockage des utilisateurs, revendications, rôles, etc. Implémentez les interfaces de tout ce que fait le code-first UserStore
et changez where TUser : IdentityUser
à where TUser : User
où "utilisateur" est votre objet d'entité
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
}
Voici quelques exemples sur certaines des implémentations d'interface
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();
}
En utilisant le modèle MVC 5, j’ai modifié le AccountController
pour qu’il ressemble à ceci.
public AccountController()
: this(new UserManager<User>(new MyUserStore<User>(new MyAppEntities())))
{
}
Maintenant, la connexion devrait fonctionner avec vos propres tables.
Regardez ce projet sur GitHub: https://github.com/KriaSoft/AspNet.Identity
Qui inclut:
Voir aussi : Comment créer un fournisseur de base de données pour ADO.NET Identity
J'ai passé plusieurs heures à travailler dessus et j'ai finalement trouvé une solution que j'ai partagée sur mon blog ici . Fondamentalement, vous devez faire tout ce qui est dit dans la réponse de puanteur mais avec une chose supplémentaire: vous assurer qu'Identity Framework dispose d'une chaîne de connexion SQL-Client spécifique au-dessus de la chaîne de connexion Entity Framework utilisée pour vos entités d'application. .
En résumé, votre application utilisera une chaîne de connexion pour Identity Framework et une autre pour les entités de votre application. Chaque chaîne de connexion est d'un type différent. Lisez mon article de blog pour un tutoriel complet.
Bonne question.
Je suis plus d'une base de données à la première personne. Le premier paradigme du code me semble lâche, et les "migrations" semblent trop sujettes aux erreurs.
Je voulais personnaliser le schéma d'identité aspnet et ne pas être dérangé par les migrations. Je connais bien les projets de base de données Visual Studio (sqlpackage, data-mec) et explique comment il fait un très bon travail de mise à niveau de schémas.
Ma solution simpliste est de:
1) Créez un projet de base de données qui reflète le schéma d’identité aspnet. 2) Utilisez la sortie de ce projet (.dacpac) en tant que ressource de projet. 3) Déployez le .dacpac si nécessaire.
Pour MVC5, la modification de la classe ApplicationDbContext
semble commencer.
1) Implémenter IDatabaseInitializer
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDatabaseInitializer<ApplicationDbContext> { ... }
2) Dans le constructeur, indiquez que cette classe implémentera l'initialisation de la base de données:
Database.SetInitializer<ApplicationDbContext>(this);
3) Implémenter InitializeDatabase
:
Ici, j’ai choisi d’utiliser DacFX et de déployer mon .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);
}
}
}
J'ai trouvé que @ JoshYates1980 avait la réponse la plus simple.
Après une série d’essais et d’erreurs, j’ai fait ce que Josh avait suggéré et remplacé le connectionString
par ma chaîne de connexion à la base de données générée. ce qui me confondait à l'origine était le post suivant:
Comment ajouter l'authentification d'identité ASP.NET MVC5 à une base de données existante
Où la réponse acceptée de @Win a déclaré changer le nom de la connexion ApplicationDbContext()
. Ceci est un peu vague si vous utilisez Entity et une première approche Base/Modèle où la chaîne de connexion à la base de données est générée et ajoutée au fichier Web.config
.
Le nom de la connexion ApplicationDbContext()
est associé à la connexion par défaut dans le fichier Web.config
. Par conséquent, la méthode de Josh fonctionne mieux, mais pour rendre la ApplicationDbContext()
plus lisible, je suggère de changer le nom de votre base de données comme @Win a été posté, en prenant soin de changer le connectionString
pour le " DefaultConnection "dans Web.config
Et commentez et/ou supprimez l'inclusion de la base de données générée par l'entité.
Nous avons un projet Entity Model DLL) dans lequel nous conservons notre classe de modèle. Nous conservons également un projet de base de données avec tous les scripts de base de données. Mon approche était la suivante:
1) Créez votre propre projet qui utilise d’abord la base de données EDMX
2) Scriptez les tables de votre base de données, j'ai utilisé VS2013 connecté à localDB (Data Connections) et copié le script dans le projet de base de données, ajoutez toutes les colonnes personnalisées, par exemple. Date de naissance [DATE] non null
3) déployer la base de données
4) Mettre à jour le projet modèle (EDMX) Ajouter au projet modèle
5) Ajouter des colonnes personnalisées à la classe d'application
public class ApplicationUser : IdentityUser
{
public DateTime BirthDate { get; set; }
}
Dans le projet MVC, AccountController a ajouté ce qui suit:
Le fournisseur d'identité veut une chaîne de connexion SQL pour que cela fonctionne. Pour ne conserver qu'une chaîne de connexion pour la base de données, extrayez la chaîne du fournisseur à partir de la chaîne de connexion 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)));
}