Entity framework 首先将SimpleMembership与EF模型一起使用
SimpleMembership能否首先与EF车型一起使用?当我尝试它时,当我调用Entity framework 首先将SimpleMembership与EF模型一起使用,entity-framework,simplemembership,Entity Framework,Simplemembership,SimpleMembership能否首先与EF车型一起使用?当我尝试它时,当我调用WebSecurity.InitializeDatabaseConnection时,我得到“找不到请求的.NET Framework数据提供程序”。 换句话说:当连接字符串使用System.Data.EntityClient提供程序时,我无法调用WebSecurity.InitializeDatabaseConnection来工作(就像首先使用模型时那样) 要重新处理此问题,请创建一个MVC 4应用程序,并将代码优
WebSecurity.InitializeDatabaseConnection时,我得到“找不到请求的.NET Framework数据提供程序”。
换句话说:当连接字符串使用System.Data.EntityClient
提供程序时,我无法调用WebSecurity.InitializeDatabaseConnection
来工作(就像首先使用模型时那样)
要重新处理此问题,请创建一个MVC 4应用程序,并将代码优先用户配置文件实体类(您可以使用MVC 4模板免费获得)替换为您在实体设计器中创建的模型优先用户类:
User
的新实体添加到模型中,其中包含Id的字段,
用户名和全名
。因此,此时,用户
数据实体是
映射到用户
表,并通过一个时髦的连接进行访问
使用System.Data.EntityClient
提供程序的字符串用户
实体。一个简单的方法
即基于用户表构造出一个用户控制器
及其关联的DbContextAccountModels.cs
文件以删除UserProfile
类和
其关联的UsersContext
类。替换对
(现在缺少)UserProfile
和UsersContext
带引用的类
到新用户类及其关联的DbContext
类初始化SimpleMembership属性
类及其引用InitializeDatabaseConnection时,它将得到一个异常。
Bob这是MVC4中的一个错误
作为一个操作过滤器,InitializeSimpleMembershipAttribute
钩住OnActionExecuting
执行延迟初始化工作,但这在生命周期中可能太晚了。如果需要执行基于角色的访问检查(在OnAuthorization
期间),Authorize属性将需要提供程序提前准备就绪。换句话说,如果对站点的第一个请求点击控制器操作,如下所示:
。。然后,当筛选器检查用户的角色但提供程序未初始化时,将出现异常
我的建议是从项目中删除ISMA,并在应用程序启动事件期间初始化Web安全性。
1-您需要启用迁移,最好是使用EntityFramework 5 2-移动你的
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "EmailAddress", autoCreateTables: true);
到您的MVCAPP/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"});
}
现在EF5将负责创建您的UserProfile表,完成此操作后,您将调用WebSecurity.InitializeDatabaseConnection以仅向已创建的UserProfile表注册SimpleMembershipProvider(在您的情况下,您可以用自定义表名替换“UserProfile”参数值),还告诉SimpleMembershipProvider哪个列是用户ID和用户名。我还展示了一个示例,说明了如何在Seed方法中添加用户、角色,以及如何将这两个角色与自定义UserProfile属性/字段关联,例如用户的手机(号码)
3-现在,当您从PackageManager控制台运行update database时,EF5将为您的表提供所有自定义属性
有关其他参考资料,请参阅本文的源代码:
我无法使用EF和WebMatrix webSecurity类,因此要避免此问题,请继续: 首先将我的Ef模型更改为代码优先 将连接字符串更改为使用providerName=“System.Data.SqlClient”(删除所有元数据信息)或使用EF连接 在我的例子中,模型、数据和web是不同的项目,因此从web.project的web.config中删除这些信息对我来说不是问题 现在websecurity.initializedatabase不使用EF连接字符串运行
我希望这有帮助SimpleMembership可以首先与model一起使用。这是解决办法 1.
InitializeSimpleMembershipAttribute.cs
来自MVC4 Internet应用程序模板,应该如下所示
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.从AcountModel.cs
3.修复AccountCotroler.cs
以首先使用模型DbContext(ExternalLoginConfirmation(registerexternallloginmodel,string returnUrl)
方法)
4.定义您的“ConnStringForWebSecurity”
连接字符串,该字符串与第一个数据库访问的时髦conn字符串不同,请注意,我们使用的是提供程序System.Data.SqlClient
而不是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>
此问题是由
网站安全性引起的。InitializedTabaseConnection
无法将连接字符串与System.Data.EntityClient
提供程序名称一起使用
提供双连接字符串听起来不太好,因此可以在分部类的构造函数中首先为EF模型生成连接字符串
代码如下所示
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)) { }
}
有了这个技巧,您可以在web配置中使用单个连接字符串,但有一个问题是,您不能在datacontext中使用默认构造函数,而是应该在任何地方使用连接字符串名称
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)) { }
}