web-dev-qa-db-fra.com

Identité ASP.NET avec la base de données EF First MVC5

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; }
87
Patrick Tran

Il devrait être possible d'utiliser le système d'identité avec POCO et Database First, mais vous devrez faire quelques ajustements:

  1. Mettez à jour le fichier .tt pour la génération POCO afin que les classes d'entité partial. Cela vous permettra de fournir une implémentation supplémentaire dans un fichier séparé.
  2. Faire une implémentation partielle de la classe User dans un autre fichier

partial 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).

16
Anders Abel

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.

13
JoshYates1980

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.

  1. Créer un projet MVC
  2. Ouvrez la base de données répertoriée sous DefaultConnection dans Web.config. Il sera appelé (aspnet- [timestamp] ou quelque chose comme ça.)
  3. Script des tables de base de données.
  4. Insérez les tables de script dans la base de données existante dans SQL Server Management Studio.
  5. Personnalisez et ajoutez des relations à ApplicationUser (si nécessaire).
  6. Créer un nouveau projet Web> MVC> Premier projet de base de données> Importer une base de données avec EF ... en excluant les classes d'identité insérées.
  7. Dans IdentityModels.cs , changez le ApplicationDbContext :base("DefaltConnection") pour utiliser le DbContext de votre projet.

Edit: Diagramme de classe d’identité Asp.Net  enter image description here

10
stink

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 Ids 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.

8
Shoe

Regardez ce projet sur GitHub: https://github.com/KriaSoft/AspNet.Identity

Qui inclut:

  • Modèle de projet de base de données SQL pour ASP.NET Identity 2.0
  • Base de données Entity Framework - Premier fournisseur (s)
  • Code source et échantillons

enter image description here

Voir aussi : Comment créer un fournisseur de base de données pour ADO.NET Identity

3
Konstantin Tarkus

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.

2
Daniel Eagle

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);
            }
        }
    }
2
Aaron Hudon

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é.

Exemples de code:

1
TheSchnitz

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)));
}
1
Haroon