Ist es möglich, die neue Asp.net-Identität mit Database First und EDMX zu verwenden? Oder erst mit Code?
Folgendes habe ich getan:
1) Ich habe ein neues MVC5-Projekt erstellt und mit der neuen Identität die neuen Benutzer- und Rollentabellen in meiner Datenbank erstellt.
2) Ich habe dann meine Database First EDMX-Datei geöffnet und in die neue Identity Users-Tabelle gezogen, da ich andere Tabellen habe, die sich darauf beziehen.
3) Beim Speichern des EDMX erstellt der Database First POCO-Generator automatisch eine Benutzerklasse. UserManager und RoleManager erwarten jedoch, dass eine Benutzerklasse vom neuen Identitätsnamespace (Microsoft.AspNet.Identity.IUser) erbt, sodass die Verwendung der POCO-Benutzerklasse nicht funktioniert.
Ich vermute, eine mögliche Lösung besteht darin, meine POCO-Generierungsklassen so zu bearbeiten, dass meine Benutzerklasse von IUser erbt.
Oder ist ASP.NET Identity nur mit Code First Design kompatibel?
++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++
Update: Nach dem Vorschlag von Anders Abel habe ich Folgendes getan. Es funktioniert, aber ich frage mich, ob es eine elegantere Lösung gibt.
1) Ich habe meine Entitätsbenutzerklasse erweitert, indem ich eine Teilklasse im selben Namespace wie meine automatisch generierten Entitäten erstellt habe.
namespace MVC5.DBFirst.Entity
{
public partial class AspNetUser : IdentityUser
{
}
}
2) Ich habe meinen DataContext so geändert, dass er von IdentityDBContext anstelle von DBContext erbt. Beachten Sie, dass Sie jedes Mal, wenn Sie Ihr EDMX aktualisieren und die DBContext- und Entity-Klassen neu generieren, dies auf diesen Wert zurücksetzen müssen.
public partial class MVC5Test_DBEntities : IdentityDbContext<AspNetUser> //DbContext
3) In Ihrer automatisch generierten Benutzerentitätsklasse müssen Sie das Überschreibungsschlüsselwort zu den folgenden 4 Feldern hinzufügen oder diese Felder auskommentieren, da sie von IdentityUser geerbt werden (Schritt 1). Beachten Sie, dass Sie jedes Mal, wenn Sie Ihr EDMX aktualisieren und die DBContext- und Entity-Klassen neu generieren, dies auf diesen Wert zurücksetzen müssen.
override public string Id { get; set; }
override public string UserName { get; set; }
override public string PasswordHash { get; set; }
override public string SecurityStamp { get; set; }
Es sollte möglich sein, das Identitätssystem mit POCO und Database First zu verwenden, aber Sie müssen einige Änderungen vornehmen:
partial
zu erstellen. Auf diese Weise können Sie zusätzliche Implementierungen in einer separaten Datei bereitstellen.User
in einer anderen Datei vorpartial User : IUser
{
}
Dadurch wird die Klasse User
die richtige Schnittstelle implementieren, ohne die tatsächlich generierten Dateien zu berühren (das Bearbeiten der generierten Dateien ist immer eine schlechte Idee).
Meine Schritte sind sehr ähnlich, aber ich wollte teilen.
1) Erstellen Sie ein neues MVC5-Projekt
2) Erstellen Sie eine neue Model.edmx. Auch wenn es eine neue Datenbank ist und keine Tabellen hat.
3) Bearbeiten Sie die Datei web.config und ersetzen Sie diese generierte Verbindungszeichenfolge:
<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" />
mit diesem verbindungsstring:
<add name="DefaultConnection" connectionString="Data Source=.\SQLExpress;database=SSFInventory;integrated security=true;" providerName="System.Data.SqlClient" />
Erstellen Sie anschließend die Anwendung, und führen Sie sie aus. Registrieren Sie einen Benutzer und dann werden die Tabellen erstellt.
EDIT: ASP.NET-Identität mit EF-Datenbank zuerst für MVC5-CodePlex-Projektvorlage.
Ich wollte eine vorhandene Datenbank verwenden und Beziehungen zu ApplicationUser erstellen. So habe ich es mit SQL Server gemacht, aber die gleiche Idee würde wahrscheinlich mit jeder DB funktionieren.
:base("DefaltConnection")
, um den DbContext Ihres Projekts zu verwenden.Bearbeiten: Asp.Net-Identitätsklassendiagramm
IdentityUser
ist hier wertlos, weil es das Code-First-Objekt ist, das von UserStore
zur Authentifizierung verwendet wird. Nachdem ich mein eigenes Objekt User
definiert hatte, implementierte ich eine Teilklasse, die IUser
implementiert, die von der Klasse UserManager
verwendet wird. Ich wollte, dass mein Id
s int
anstelle von string ist, also gebe ich einfach die UserID an String () zurück. Ebenso wollte ich, dass n
in Username
nicht kapitalisiert wird.
public partial class User : IUser
{
public string Id
{
get { return this.UserID.ToString(); }
}
public string UserName
{
get
{
return this.Username;
}
set
{
this.Username = value;
}
}
}
Sie brauchen auf keinen Fall IUser
. Es ist nur eine Schnittstelle, die vom UserManager
verwendet wird. Wenn Sie also einen anderen "IUser" definieren möchten, müssen Sie diese Klasse neu schreiben, um Ihre eigene Implementierung zu verwenden.
public class UserManager<TUser> : IDisposable where TUser: IUser
Sie schreiben jetzt Ihr eigenes UserStore
, das die gesamte Speicherung von Benutzern, Ansprüchen, Rollen usw. verwaltet. Implementieren Sie die Schnittstellen von allem, was das Code-first UserStore
tut und ändert where TUser : IdentityUser
bis where TUser : User
wobei "Benutzer" Ihr Entitätsobjekt ist
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
}
Hier einige Beispiele für einige Schnittstellenimplementierungen
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();
}
Mit der MVC 5-Vorlage habe ich AccountController
so geändert.
public AccountController()
: this(new UserManager<User>(new MyUserStore<User>(new MyAppEntities())))
{
}
Jetzt sollte die Anmeldung mit Ihren eigenen Tabellen funktionieren.
Schauen Sie sich dieses Projekt auf GitHub an: https://github.com/KriaSoft/AspNet.Identity
Welches beinhaltet:
Siehe auch : So erstellen Sie einen Database-First-Provider für ADO.NET Identity
Ich habe mich mehrere Stunden damit beschäftigt und endlich eine Lösung gefunden, die ich auf meinem Blog geteilt habe hier . Grundsätzlich müssen Sie alles tun, was in der Antwort von stink gesagt wurde, aber mit einer zusätzlichen Sache: Sicherstellen, dass Identity Framework eine spezifische SQL-Client-Verbindungszeichenfolge über der für Ihre Anwendungsentitäten verwendeten Entity Framework-Verbindungszeichenfolge verfügt .
Zusammenfassend wird Ihre Anwendung eine Verbindungszeichenfolge für Identity Framework und eine andere für Ihre Anwendungsentitäten verwenden. Jede Verbindungszeichenfolge hat einen anderen Typ. In meinem Blogbeitrag finden Sie eine vollständige Anleitung.
Gute Frage.
Ich bin eher eine Datenbank-First-Person. Das Code-First-Paradigma scheint mir verworren zu sein, und die "Migrationen" scheinen zu fehleranfällig.
Ich wollte das Aspnet-Identitätsschema anpassen und mich nicht um Migrationen kümmern. Ich bin mit Visual Studio-Datenbankprojekten (sqlpackage, data-dude) bestens vertraut und verstehe, wie sich Schemas aufrüsten lassen.
Meine vereinfachende Lösung lautet:
1) Erstellen Sie ein Datenbankprojekt, das das Aspnet-Identitätsschema widerspiegelt. 2) Verwenden Sie die Ausgabe dieses Projekts (.dacpac) als Projektressource. 3) Stellen Sie das .dacpac bei Bedarf bereit
In MVC5 scheint das Ändern der Klasse ApplicationDbContext
in Gang zu kommen ...
1) Implementiere IDatabaseInitializer
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDatabaseInitializer<ApplicationDbContext> { ... }
2) Geben Sie im Konstruktor an, dass diese Klasse die Datenbankinitialisierung implementiert:
Database.SetInitializer<ApplicationDbContext>(this);
3) Implementiere InitializeDatabase
:
Hier habe ich mich für DacFX entschieden und meinen .dacpac bereitgestellt
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);
}
}
}
Ich fand, dass @ JoshYates1980 die einfachste Antwort hat.
Nach einer Reihe von Versuchen und Fehlern tat ich, was Josh vorschlug, und ersetzte die connectionString
durch meine generierte DB-Verbindungszeichenfolge. Was mich ursprünglich verwirrte, war der folgende Beitrag:
Hinzufügen der ASP.NET MVC5-Identitätsauthentifizierung zu einer vorhandenen Datenbank
Wobei die akzeptierte Antwort von @Win angab, den ApplicationDbContext()
Verbindungsnamen zu ändern. Dies ist etwas vage, wenn Sie Entity und einen Datenbank-/Modell-Ansatz verwenden, bei dem die Datenbankverbindungszeichenfolge generiert und der Datei Web.config
Hinzugefügt wird.
Der Verbindungsname ApplicationDbContext()
wird der Standardverbindung in der Datei Web.config
Zugeordnet . Daher funktioniert Joshs Methode am besten, aber um die Lesbarkeit von ApplicationDbContext()
zu verbessern, würde ich vorschlagen, den Namen in den Namen Ihrer Datenbank zu ändern, der ursprünglich als @Win gepostet wurde, und dabei die connectionString
für das zu ändern "DefaultConnection" im Web.config
Auskommentieren und/oder die Entity generierte Datenbank entfernen.
Wir haben ein Entitätsmodell DLL Projekt, in dem wir unsere Modellklasse behalten. Wir haben auch ein Datenbankprojekt mit allen Datenbankskripten. Mein Ansatz war wie folgt
1) Erstellen Sie zuerst ein eigenes Projekt mit der EDMX-Datenbank
2) Erstellen Sie ein Skript für die Tabellen in Ihrer Datenbank. Ich habe VS2013 verwendet, das mit localDB (Data Connections) verbunden ist, und das Skript in das Datenbankprojekt kopiert. Fügen Sie benutzerdefinierte Spalten hinzu, z. BirthDate [DATE] ist nicht null
3) Stellen Sie die Datenbank bereit
4) Aktualisieren Sie das Modellprojekt (EDMX). Fügen Sie es dem Modellprojekt hinzu
5) Fügen Sie der Anwendungsklasse benutzerdefinierte Spalten hinzu
public class ApplicationUser : IdentityUser
{
public DateTime BirthDate { get; set; }
}
Im MVC-Projekt AccountController wurde Folgendes hinzugefügt:
Der Identitätsanbieter möchte, dass eine SQL-Verbindungszeichenfolge funktioniert. Um nur eine Verbindungszeichenfolge für die Datenbank beizubehalten, extrahieren Sie die Anbieterzeichenfolge aus der EF-Verbindungszeichenfolge
public AccountController()
{
var connection = ConfigurationManager.ConnectionStrings["Entities"];
var entityConnectionString = new EntityConnectionStringBuilder(connection.ConnectionString);
UserManager =
new UserManager<ApplicationUser>(
new UserStore<ApplicationUser>(
new ApplicationDbContext(entityConnectionString.ProviderConnectionString)));
}