我在我的MVC应用程序中实现了自定义角色提供程序,但是当同时发出多个同时授权请求时,我收到以下错误 {“连接未关闭。连接的当前状态正在连接。”}
这发生在我的UserRepository文件中的行上。
var user = _db.Users.SingleOrDefault(u => u.userName == username);
这里的其他线程的建议是我应该在我的UserRepository文件的每个方法中单独实例化_db Context。这确实解决了这个问题,但是我在其他地方已经读过我应该使用ISession来共享DataContexts。应用程序只有一个DataContext但是有多个存储库使用它。所以,如果有人能够确认通过将_db Context移动到每个方法的开头,我会做正确的事情,然后我才能进入这个项目,我会非常感激。
提前致谢
我按照执行顺序附上了相关文件。
文件:Global.asax.cs
void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
string encTicket = authCookie.Value;
if (!String.IsNullOrEmpty(encTicket))
{
var ticket = FormsAuthentication.Decrypt(encTicket);
var id = new UserIdentity(ticket);
var userRoles = Roles.GetRolesForUser(id.Name); //Method in Question
var prin = new MyPrincipal(id, userRoles);
string userData = ((FormsIdentity)(Context.User.Identity)).Ticket.UserData;
var serializer = new JavaScriptSerializer();
prin.User = (User)serializer.Deserialize(userData, typeof(User));
HttpContext.Current.User = prin;
}
}
}
文件:CustomRoleProvider.cs
namespace CMS3.Infrastructure
{
public class CustomRoleProvider : RoleProvider
{
private ILoginRepository _rep;
public CustomRoleProvider(ILoginRepository rep)
{
_rep = rep;
}
public CustomRoleProvider()
: this(new UserRepository())
{ }
public override string[] GetRolesForUser(string username)
{
var roles = _rep.GetRolesForUser(username);
return roles;
}
}
}
文件:userRepository.cs
namespace CMS3.Ef.Repositories
{
public class UserRepository : ILoginRepository
{
CMS3Context _db = new CMS3Context();
static PasswordManager pwdManager = new PasswordManager();
string[] ILoginRepository.GetRolesForUser(string username)
{
var user = _db.Users.SingleOrDefault(u => u.userName == username);
if (user == null)
return new string[] { };
return user.UserRoles == null ? new string[] { } : user.UserRoles.Select(u =>u.Role).Select(u => u.roleName).ToArray();
}
}
文件:ILoginRepository.cs
namespace CMS3.Model.InterfaceRepositories
{
public interface ILoginRepository : IDisposable
{
tblLogin UserByID(int id);
LoginDetails UserByNamePassword(string userName, string password);
LoginDetails UserByName(string userName);
bool IsUserInRole(string username, string roleName);
string[] GetRolesForUser(string username);
string[] GetAllRoles();
List<UsersSearchDetails> GetUsers(int count = 0);
List<UsersSearchDetails> GetUsers(string searchUser);
UsersSearchDetails GetUser(int id);
bool AdminChangePassword(int id, string newPassword);
bool deActivateUser(int id);
List<RoleDetails> getUserRoles(int id);
List<RoleDetails> getAvaiableRoles(int id);
bool AddRoleToUser(int id, int role);
bool RemoveRoleFromUser(int id, int role);
bool UpdateLoginStatus(string userName, bool loginFail);
string[] SearchUsers(string term);
}
}
答案 0 :(得分:0)
这里的其他线程的建议是我应该在我的UserRepository文件的每个方法中单独实例化_db Context。 [...]所以如果有人可以通过将_db Context移动到每个方法的开头来确认这一点我真的很高兴我在做好这个项目之前做了正确的事情。
这与你应该做的完全相反。每个存储库有一个额外的dbcontext意味着第一级缓存(身份映射)的好处会丢失,每个存储库都会自行缓存数据。
相反,您应该使存储库实现依赖于dbcontext的生命周期管理的外部方式:
public class UserRepository : ILoginRepository
{
CMS3Context _db;
public UserRepository( CMS3Context db )
{
this._db = db;
}
...
}
这样,您可以在MVC应用程序中注入上下文(例如,是否共享),通常每个http请求都有一个上下文。