J'ai été confronté à une nouvelle fonctionnalité ASP MVC 4, elle est livrée avec un nouveau schéma de base de données d'appartenance et une nouvelle initialisation. mais maintenant je fais face à la méthode dans l'espace de noms des filtres dans le projet mvc 4 par défaut:
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
et tableau de profil utilisateur:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
}
Mais la méthode InitializeDatabaseConnection ne génère que UserName et UserId dont j'ai besoin pour générer d'autres champs supplémentaires.
J'ai une bonne expérience de l'approche EF codeFirst, et dans ce cas, j'essaie de modifier la classe UserProfile:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
[Column]
[Required]
public string UserName { get; set; }
[Column]
[Required]
public string FirstName { get; set; }
[Column]
[Required]
public string LastName { get; set; }
}
Mais lorsque je régénère la base de données, je ne vois aucun changement, les champs de base de données personnalisés ne sont pas générés. Aidez-moi s'il vous plaît, comment puis-je créer des champs utilisateur personnalisés?
Élaborer à partir de la réponse ci-dessus
Le WebSecurity.InitializeDatabaseConnection
L'aide de la méthode indique que
Si vous souhaitez utiliser une table de base de données contenant des informations de profil utilisateur (noms d'utilisateurs, adresses e-mail, etc.), vous spécifiez une chaîne de connexion et un nom de table que le système d'appartenance utilise pour se connecter à ces informations. Si vous ne souhaitez pas utiliser une table de profil utilisateur existante, vous pouvez spécifier que la méthode InitializeDatabaseConnection () doit automatiquement créer la table de profil utilisateur. (Une base de données pour la table des profils utilisateur doit déjà exister.)
Donc, si nous voulons plus de champs dans la table UserProfile
, nous devons juste nous assurer que nous créons une table de profil et exécuter la méthode InitializeDatabaseConnection
une fois que la table est déjà en place.
Dans le modèle de projet MVC4.0 standard de VS2012, j'ai commenté le contrôleur de compte
[Authorize]
//[InitializeSimpleMembership]
public class AccountController : Controller
{
et déplacé InitializeDatabaseConnection
dans l'EF Code First Database Initializer
public class MyDatabaseInit: DropCreateDatabaseAlways<MyDatabaseContext>
{
protected override void Seed(MyDatabaseContext context)
{
SeedMembership();
}
private void SeedMembership()
{
WebSecurity.InitializeDatabaseConnection("MyDatabaseContext",
"UserProfile", "UserId", "UserName", autoCreateTables: true);
}
}
s'assurer que InitializeDatabaseConnection
s'exécute une fois que la table est déjà en place.
Ajout de la classe UserProfile
à mon modèle EF Code First
public class MyDatabaseContext : DbContext
{
public DbSet<UserProfile> UserProfiles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Ajout du champ supplémentaire dans la table UserProfile
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string MobilePhone { get; set; }
}
Tout ce dont vous avez besoin maintenant est de définir la stratégie d'initialisation de la base de données au démarrage de l'application et également d'appeler une requête sur la base de données pour vous assurer qu'elle est créée à ce stade, avant d'appeler un code d'autorisation/d'authentification.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Database.SetInitializer<MyDatabaseContext>(new MyDatabaseInit());
new MyDatabaseContext().UserProfile.Find(1);
}
Je suis juste tombé sur ce problème et j'ai dû dénouer la bonne façon de le faire à partir de la réponse + commentaires (+ essais et erreurs), alors j'ai pensé partager les résultats que vous pouvez couper et coller. Ceci est basé sur la réponse d'IMLiviu, donc un crédit complet pour eux. Il modifie les classes UserProfile
et UserContext
existantes car elles semblent directement compatibles avec EF telles quelles:
J'ai été horrifié de voir une suggestion qui impliquait de supprimer complètement une base de données, juste pour ajouter quelques tableaux, donc après avoir lu tous les commentaires et créé un prototype, voici le résultat.
Arrêtez la création de matrice Web standard des tables d'appartenance (mettez en commentaire l'attribut [InitializeSimpleMembership]).
[Authorize]
//[InitializeSimpleMembership]
public class AccountController : Controller
Créez une classe de configuration de migration comme celle ci-dessous:
public class MigrationConfiguration : DbMigrationsConfiguration<UsersContext>
{
public MigrationConfiguration()
{
this.AutomaticMigrationsEnabled = true; // This is important as it will fail in some environments (like Azure) by default
}
protected override void Seed(UsersContext context)
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
}
Modifiez la classe UsersContext
du fichier AccountModel.cs pour supprimer l'option de pluralisation (ajout de l'événement OnModelCreating):
public class UsersContext : DbContext
{
public UsersContext() : base("DefaultConnection")
{
}
public DbSet<UserProfile> UserProfiles { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Ajoutez les champs supplémentaires dont vous avez besoin à UserProfile:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string UserEmail { get; set; } // <<<<<<<< E.G. THIS ADDED
}
Maintenant, lorsque l'application démarre, vous définissez la stratégie d'initialisation de la base de données et la déclenchez avec une lecture:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
Database.SetInitializer(new MigrateDatabaseToLatestVersion<UsersContext, MigrationConfiguration>());
new UsersContext().UserProfiles.Find(1);
}
Évidemment, vous devrez ajouter diverses instructions using pour que tout cela fonctionne, mais l'option clic droit résoudre le fera pour vous.
Si vous décidez (comme je l'ai fait) d'utiliser une table autre que UserProfile
pour vos utilisateurs, vous devez modifier plusieurs entrées pour qu'elles correspondent.
SimpleMembershipInitializer
, vous devez référencer les nouveaux noms de table et de colonneUsersContext
, vous pouvez laisser le nom de classe Userprofile tel quel, mais vous devez modifier l'attribut Table
pour qu'il corresponde au nom de votre table.UserProfile
, vous devez renommer les champs pour qu'ils correspondent à vos nouveaux noms de champ de table.webpages_UsersInRoles
et UserProfile
et ajoutez une relation entre votre nouvelle table utilisateur et webpages_UsersInRoles
ou les anciennes vérifications d'intégrité référentielle vous briseront au moment de l'exécution. (Je vous recommande fortement de supprimer la table UserProfile
existante et de vérifier qu'elle n'est pas recréée. Si c'est le cas, il vous reste quelque chose dans votre code).Ajoutez une nouvelle table à la base de données et appelez-la User_Details ou similaire, lors de la création d'un utilisateur, vous pouvez ensuite récupérer l'ID de l'utilisateur et forcer les détails dans la nouvelle table. Ceci est une option simple.
Jetez un œil au modèle de projet Internet MVC4 fourni avec VS2012 ou VS2010. Vous devez vous assurer que la base de données n'est pas créée avant de modifier les colonnes de votre classe userprofile. vous pouvez ajouter plus de propriétés dans vos classes POCO, puis régénérer votre base de données. si vous ajoutez des propriétés après la génération de la base de données, assurez-vous que vous utilisez les migrations EF pour ajouter ces nouvelles propriétés à la base de données
Bien sûr, vous savez probablement que vous devez rendre votre RegisterModel
identique à UserProfile Model
. Ce que j'aime faire, c'est utiliser Migrations avant d'initialiser la base de données et mettre ce qui suit dans le Configuration.cs
fichier:
protected override void Seed(UsersContext context)
{
WebSecurity.InitializeDatabaseConnection(
"DefaultConnection",
"UserProfile",
"UserId",
"UserName", autoCreateTables: true);
if (!WebSecurity.UserExists("yardpenalty"))
WebSecurity.CreateUserAndAccount(
"yardpenalty",
"password",
new
{
Email = "[email protected]",
ImageUrl = "/Content/Avatars/yourname",
DateJoined = DateTime.Now
},
false);
//... rest of model.Builder stuff
}
Ensuite, j'utilise le Packet Manager Console
par ces trois commandes faciles à mémoriser:
Je suis d'accord avec TrueBlueAussie , et j'irais jusqu'à dire que LazyInitialization n'est plus très utile et vous n'avez vraiment plus besoin de l'appeler comme vous l'avez fait. Quoi qu'il en soit, tout ce que vous avez à faire est de changer votre action d'enregistrement dans votre contrôleur de compte pour appeler la méthode comme ceci:
WebSecurity.CreateUserAndAccount(model.UserName, model.Password, propertyValues: new { model.Email, model.ImageUrl, model.DateJoined });
REMARQUE: MVC5 utilise OWIN