entity framework - framework - Usando SimpleMembership con el modelo EF primero
entity framework ejemplo (5)
¿ Se puede usar SimpleMembership con el modelo EF primero ? Cuando lo intento, obtengo "No se puede encontrar el proveedor de datos de .NET Framework solicitado" cuando llamo a WebSecurity.InitializeDatabaseConnection.
Para decirlo de otra manera: no puedo hacer que la llamada a WebSecurity.InitializeDatabaseConnection
funcione cuando la cadena de conexión emplea el proveedor System.Data.EntityClient
(como lo hace cuando se usa el primer paradigma del modelo ).
Para volver a solucionar el problema, cree una aplicación MVC 4 y reemplace la clase de entidad UserProfile ( código primero de código) (que puede obtener gratis con la plantilla MVC 4) con una clase de usuario de primer modelo que haya creado en el diseñador de entidades:
- Cree una aplicación MVC 4 en VS 2012 y agregue un nuevo modelo de datos de entidad en blanco.
- Agregue una nueva Entidad llamada
User
al modelo, con campos paraId,
UserName, and FullName
. Por lo tanto, en este punto, la entidad de datos deUser
se asigna a una tabla deUsers
y se accede a través de una cadena de conexión funky que emplea el proveedorSystem.Data.EntityClient
. - Verifique que el EF pueda acceder a la entidad
User
. Una forma fácil de hacerlo es armar un controlador de Usuarios en función de la tabla de Usuarios y su DbContext asociado. - Edite el archivo
AccountModels.cs
para eliminar la claseUserProfile
y su clase asociadaUsersContext
. Reemplace las referencias a las clasesUserProfile
yUsersContext
(ahora faltantes) con referencias a su nueva clase User y su claseDbContext
asociada. - Mueva la llamada a InitializeDatabaseConnection de la clase de filtro InitializeSimpleMembershipAttribute al método Application_Start en Global.asax.cs. Mientras lo hace, modifique los argumentos para usar la nueva cadena de conexión de la entidad Usuario, el nombre de la tabla y el nombre de la columna UserId.
- Elimine la clase
InitializeSimpleMembershipAttribute
(que ya no se usa) y las referencias a ella.
Cuando ejecute la reproducción, obtendrá una excepción en la llamada a InitializeDatabaseConnection.
Mover
1: debe habilitar las migraciones, preferiblemente con EntityFramework 5
2 - Mueve tu
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "EmailAddress", autoCreateTables: true);
a su método Seed en su clase YourMvcApp / Migrations / Configuration.cs
protected override void Seed(UsersContext context)
{
WebSecurity.InitializeDatabaseConnection(
"DefaultConnection",
"UserProfile",
"UserId",
"UserName", autoCreateTables: true);
if (!Roles.RoleExists("Administrator"))
Roles.CreateRole("Administrator");
if (!WebSecurity.UserExists("lelong37"))
WebSecurity.CreateUserAndAccount(
"lelong37",
"password",
new {Mobile = "+19725000000", IsSmsVerified = false});
if (!Roles.GetRolesForUser("lelong37").Contains("Administrator"))
Roles.AddUsersToRoles(new[] {"lelong37"}, new[] {"Administrator"});
}
Ahora EF5 se encargará de crear su tabla UserProfile, después de hacerlo, llamará a WebSecurity.InitializeDatabaseConnection para registrar solo SimpleMembershipProvider con la tabla UserProfile ya creada (en su caso, puede reemplazar el valor del parámetro "UserProfile" con su tabla personalizada nombre) , también indica a SimpleMembershipProvider qué columna es UserId y UserName. También estoy mostrando un ejemplo de cómo puede agregar usuarios, roles y asociar los dos en su método Seed con propiedades / campos personalizados de perfil de usuario, por ejemplo, el número de teléfono móvil de un usuario.
3 - Ahora, cuando ejecute la base de datos de actualización desde la Consola del Administrador de Paquetes, EF5 aprovisionará su tabla con todas sus propiedades personalizadas
Para referencias adicionales, consulte este artículo con el código fuente: http://blog.longle.net/2012/09/25/seeding-users-and-roles-with-mvc4-simplemembershipprovider-simpleroleprovider-ef5-codefirst-and-custom-user-properties/
Eso es un error en MVC 4. Hay una solución en esta publicación del blog .
Como filtro de acción,
InitializeSimpleMembershipAttribute
enlaza conOnActionExecuting
para realizar el trabajo de inicialización lento, pero esto puede ser demasiado tarde en el ciclo de vida. El atributo Autorizar necesitará que los proveedores estén listos antes si necesita realizar verificaciones de acceso basadas en roles (durante laOnAuthorization
). En otras palabras, si la primera solicitud a un sitio realiza una acción de controlador como la siguiente:
[Authorize(Roles="Sales")]
... entonces tendrá una excepción, ya que el filtro verifica la función del usuario pero los proveedores no están inicializados.
Mi recomendación es eliminar ISMA del proyecto e inicializar WebSecurity durante el evento de inicio de la aplicación.
No puedo trabajar con la clase webSecurity de EF y WebMatrix para evitar este problema y seguir adelante:
Cambie mi modelo de Ef primero para codificar primero.
Cambie la cadena de conexión para usar providerName = "System.Data.SqlClient" (eliminando toda la información de metadatos) o use la conexión EF
En mi caso, el modelo, los datos y la web son proyectos diferentes, así que para mí no es un problema eliminar esta información de web.config en web.project.
Hoy en día websecuroty.initializedatabase no se ejecuta con la cadena de conexión EF.
Deseo que esto ayude
SimpleMembership puede trabajar con el modelo primero. Aquí está la solución.
1. InitializeSimpleMembershipAttribute.cs
de la aplicación de Internet MVC 4 templete debería tener este aspecto
namespace WebAndAPILayer.Filters
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
try
{
WebSecurity.InitializeDatabaseConnection("ConnStringForWebSecurity", "UserProfile", "Id", "UserName", autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("Something is wrong", ex);
}
}
}
}
}
2.Elimine las clases AcountModel.cs
de AcountModel.cs
3.Fix AccountCotroler.cs
para trabajar con su modelo DbContext ( ExternalLoginConfirmation(RegisterExternalLoginModel model, string returnUrl)
)
4. Defina su cadena de conexión "ConnStringForWebSecurity"
que no es la misma que la cadena funky conn para el acceso a la base de datos del modelo primero, observe que usamos el proveedor System.Data.SqlClient
no System.Data.EntityClient
<connectionStrings>
<add name="ModelFirstEntityFramework" connectionString="metadata=res://*/Context.csdl|res://*/Context.ssdl|res://*/Context.msl;provider=System.Data.SqlClient;provider
connection string="data source=./SQLEXPRESS;Initial
Catalog=aspnet-MVC4;Integrated
Security=SSPI;multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
<add name="ConnStringForWebSecurity" connectionString="data source=./SQLEXPRESS;Initial Catalog=aspnet-MVC4;Integrated
Security=SSPI" providerName="System.Data.SqlClient" />
</connectionStrings>
este problema causado por WebSecurity.InitializeDatabaseConnection
no puede usar la cadena de conexión con el nombre del proveedor System.Data.EntityClient
.
proporcionar una cadena de conexión dual no suena bien, por lo que puede generar la cadena de conexión para el modelo EF primero en el constructor en la clase parcial.
el código se ve como abajo
public partial class MyDataContext
{
private static string GenerateConnectionString(string connectionString)
{
var cs = System.Configuration.ConfigurationManager
.ConnectionStrings[connectionString];
SqlConnectionStringBuilder sb =
new SqlConnectionStringBuilder(cs.ConnectionString);
EntityConnectionStringBuilder builder =
new EntityConnectionStringBuilder();
builder.Provider = cs.ProviderName;
builder.ProviderConnectionString = sb.ConnectionString;
builder.Metadata = "res://*/MyDataContext.csdl|" +
"res://*/MyDataContext.ssdl|res://*/MyDataContext.msl";
return builder.ToString();
}
public MyDataContext(string connectionName) :
base(GenerateConnectionString(connectionName)) { }
}
con este truco, puede usar una sola cadena de conexión en su configuración web, pero un problema no puede usar el constructor predeterminado en su contexto de datos, en lugar de ello, debe colocar el nombre de la cadena de conexión en todas partes cuando cree una instancia del vínculo de datos. pero no es un gran problema cuando usa el patrón de inyección de dependencia.