asp.net - university - update model from database entity framework
Identidad de ASP.NET con la base de datos EF First MVC5 (9)
Buena pregunta.
Soy más una persona de base de datos. El primer paradigma del código me parece irrespirable, y las "migraciones" parecen demasiado propensas a errores.
Quería personalizar el esquema de identidad de aspnet y no molestarme con las migraciones. Estoy muy versado con los proyectos de base de datos de Visual Studio (paquete sql, tipo de datos) y cómo hace un trabajo bastante bueno en la actualización de esquemas.
Mi solución simplista es:
1) Cree un proyecto de base de datos que refleje el esquema de identidad de aspnet 2) use el resultado de este proyecto (.dacpac) como recurso de proyecto 3) implemente el .dacpac cuando sea necesario
Para MVC5, la modificación de la clase ApplicationDbContext
parece poner esto en marcha ...
1) Implementar IDatabaseInitializer
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IDatabaseInitializer<ApplicationDbContext> { ... }
2) En el constructor, señal de que esta clase implementará la inicialización de la base de datos:
Database.SetInitializer<ApplicationDbContext>(this);
3) Implementar InitializeDatabase
:
Aquí, elegí usar DacFX y desplegar mi .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);
}
}
}
¿Es posible usar la nueva Identidad Asp.net con Database First y EDMX? ¿O solo con el código primero?
Esto es lo que hice:
1) Hice un nuevo Proyecto MVC5 y tuve la nueva Identidad crear las nuevas tablas de Usuario y Roles en mi base de datos.
2) Luego abrí mi archivo Database First EDMX y lo arrastré a la nueva tabla Identity Users, ya que tengo otras tablas relacionadas con él.
3) Al guardar el EDMX, el generador de la base de datos First POCO creará automáticamente una clase de usuario. Sin embargo, UserManager y RoleManager esperan que una clase de Usuario herede del nuevo espacio de nombres de Identidad (Microsoft.AspNet.Identity.IUser), por lo que el uso de la clase de Usuario POCO no funcionará.
Supongo que una posible solución es editar mis clases de generación de POCO para que mi clase de usuario herede de IUser.
¿O la identidad ASP.NET solo es compatible con Code First Design?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++
Actualización: siguiendo la sugerencia de Anders Abel a continuación, esto es lo que hice. Funciona, pero me pregunto si hay una solución más elegante.
1) Extendí la clase de usuario de mi entidad creando una clase parcial dentro del mismo espacio de nombres que mis entidades generadas automáticamente.
namespace MVC5.DBFirst.Entity
{
public partial class AspNetUser : IdentityUser
{
}
}
2) Cambié mi DataContext para heredar de IdentityDBContext en lugar de DBContext. Tenga en cuenta que cada vez que actualice su EDMX y regenere las clases DBContext y Entity, tendrá que volver a configurar esto.
public partial class MVC5Test_DBEntities : IdentityDbContext<AspNetUser> //DbContext
3) Dentro de la clase de entidad de usuario generada automáticamente, debe agregar la palabra clave de anulación a los siguientes 4 campos o comentar estos campos, ya que se heredan de IdentityUser (Paso 1). Tenga en cuenta que cada vez que actualice su EDMX y regenere las clases DBContext y Entity, tendrá que volver a configurar esto.
override public string Id { get; set; }
override public string UserName { get; set; }
override public string PasswordHash { get; set; }
override public string SecurityStamp { get; set; }
Debería ser posible usar el sistema de identidad con POCO y Database First, pero tendrás que hacer un par de ajustes:
- Actualice el archivo .tt para generación POCO para hacer que las clases de entidad sean
partial
. Eso le permitirá suministrar una implementación adicional en un archivo separado. - Realice una implementación parcial de la clase
User
en otro archivo
partial User : IUser
{
}
Esto hará que la clase de User
implemente la interfaz correcta, sin tocar los archivos generados reales (la edición de archivos generados siempre es una mala idea).
Descubrí que @ JoshYates1980 tiene la respuesta más simple.
Después de una serie de pruebas y errores, hice lo que Josh sugirió y reemplacé el connectionString
con mi cadena de conexión DB generada. Lo que me confundió originalmente fue la siguiente publicación:
Cómo agregar Autenticación de identidad ASP.NET MVC5 a una base de datos existente
Donde la respuesta aceptada de @Win declaró cambiar el nombre de conexión de ApplicationDbContext()
. Esto es un poco vago si usa Entity y un primer enfoque de Base de datos / Modelo donde se genera la cadena de conexión de la base de datos y se agrega al archivo Web.config
.
El nombre de conexión de ApplicationDbContext()
se asigna a la conexión predeterminada en el archivo Web.config
. Por lo tanto, el método de Josh funciona mejor, pero para hacer que ApplicationDbContext()
más legible, sugeriría cambiar el nombre al nombre de su base de datos como @Win originalmente publicado, asegurándose de cambiar el connectionString
para la " connectionString
predeterminada" en el Web.config
y comentar y / o eliminar la base de datos generada por la entidad incluye.
Eche un vistazo a este proyecto en GitHub: https://github.com/KriaSoft/AspNet.Identity
Que incluye:
- Plantilla de proyecto de base de datos SQL para ASP.NET Identity 2.0
- Base de datos de Entity Framework: primer proveedor (es)
- Código fuente y muestras
https://github.com/KriaSoft/AspNet.Identity
Consulte también : Cómo crear un proveedor de base de datos para ADO.NET Identity
Mis pasos son muy similares, pero quería compartirlos.
1) Crear un nuevo proyecto MVC5
2) Crea un nuevo Model.edmx. Incluso si es una base de datos nueva y no tiene tablas.
3) Edite web.config y reemplace esta connectionString generada:
<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" />
con esta connectionstring:
<add name="DefaultConnection" connectionString="Data Source=./SQLExpress;database=SSFInventory;integrated security=true;" providerName="System.Data.SqlClient" />
Luego, compila y ejecuta la aplicación. Registra un usuario y luego se crearán las tablas.
Pasé varias horas trabajando en esto y finalmente encontré una solución que he compartido en mi blog here . Básicamente, debe hacer todo lo dicho en la respuesta a , pero con una cosa adicional: garantizar que Identity Framework tenga una cadena de conexión SQL-Client específica encima de la cadena de conexión de Entity Framework utilizada para las entidades de su aplicación.
En resumen, su aplicación usará una cadena de conexión para Identity Framework y otra para sus entidades de aplicación. Cada cadena de conexión es de un tipo diferente. Lea la publicación de mi blog para obtener un tutorial completo.
Tenemos un proyecto de Entity Model DLL donde guardamos nuestra clase de modelo. También mantenemos un proyecto de base de datos con todas las secuencias de comandos de la base de datos. Mi enfoque fue el siguiente
1) Cree su propio proyecto que tenga la base de datos EDMX primero
2) Script de las tablas en su base de datos, usé VS2013 conectado a localDB (Conexiones de datos) y copié el script en el proyecto de base de datos, agregué cualquier columna personalizada, por ejemplo, BirthDate [DATE] no null
3) Implementar la base de datos
4) Actualizar el proyecto de modelo (EDMX) Agregar al proyecto de modelo
5) Agregue cualquier columna personalizada a la clase de aplicación
public class ApplicationUser : IdentityUser
{
public DateTime BirthDate { get; set; }
}
En el proyecto MVC, AccountController agregó lo siguiente:
El proveedor de identidad desea una cadena de conexión SQL para que funcione, para mantener solo 1 cadena de conexión para la base de datos, extraer la cadena del proveedor de la cadena de conexión 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)));
}
IdentityUser
es inútil aquí porque es el objeto de primer código utilizado por la UserStore
de UserStore
para la autenticación. Después de definir mi propio objeto de User
, implementé una clase parcial que implementa IUser
que es usado por la clase UserManager
. Quería que mis Id
fueran int
lugar de cadena, así que simplemente devuelvo los UserSt a toString (). Del mismo modo, quería que n
en Username
de Username
estuviera 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;
}
}
}
Usted de ninguna manera necesita IUser
. Es solo una interfaz utilizada por el UserManager
. Por lo tanto, si desea definir un "IUser" diferente, deberá volver a escribir esta clase para usar su propia implementación.
public class UserManager<TUser> : IDisposable where TUser: IUser
Ahora escribe su propia UserStore
que maneja todo el almacenamiento de usuarios, reclamos, roles, etc. Implemente las interfaces de todo lo que hace la primera UserStore
código y cambie where TUser : IdentityUser
a where TUser : User
donde "User" es su objeto de entidad
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
}
Aquí hay un par de ejemplos sobre algunas de las implementaciones de interfaz
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();
}
Usando la plantilla MVC 5, cambié el AccountController
para que se vea así.
public AccountController()
: this(new UserManager<User>(new MyUserStore<User>(new MyAppEntities())))
{
}
Ahora iniciar sesión debería funcionar con sus propias tablas.
EDITAR: Identidad ASP.NET con la base de datos EF Primero para la plantilla de proyecto MVC5 CodePlex.
Quería usar una base de datos existente y crear relaciones con ApplicationUser. Así es como lo hice usando SQL Server pero la misma idea probablemente funcionaría con cualquier DB.
- Crear un proyecto MVC
- Abra la base de datos que figura en DefaultConnection en Web.config. Se llamará (aspnet- [timestamp] o algo así).
- Script las tablas de la base de datos.
- Inserte las tablas con guiones en la base de datos existente en SQL Server Management Studio.
- Personalice y agregue relaciones a ApplicationUser (si es necesario).
- Cree un nuevo proyecto web> MVC> DB First Project> Importar base de datos con EF ... Excluyendo las clases de identidad que ha insertado.
- En IdentityModels.cs, cambie ApplicationDbContext
:base("DefaltConnection")
para usar el DbContext de su proyecto.
Editar: Asp.Net Identity Class Diagram