问题
My role provider looks like the class below (abridged). I am running on IIS Express, and SQL 2012 Express, from VS 2012, and I get a multitude of seemingly random exceptions in this role provider code.
public class Educ8RoleProvider : RoleProvider
{
private readonly Educ8DbContext _dbContext = new Educ8DbContext();
private readonly Authorization _authorization;
public Educ8RoleProvider()
{
_authorization = new Authorization(_dbContext);
}
public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
{
try
{
base.Initialize(name, config);
}
catch (Exception ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
throw;
}
}
public override bool IsUserInRole(string username, string roleName)
{
return GetRolesForUser(username).Any(r => r.ToLower() == roleName);
}
public override string[] GetRolesForUser(string username)
{
return _authorization.GetRolesForMember(username).Select(r => r.Name).ToArray();
}
}
Here is a sample of my Authorization
class:
public class Authorization
{
private readonly Educ8DbContext _dbContext;
private readonly IMemberRepository _memberRepository;
private readonly IRoleRepository _roleRepository;
private readonly IMemberRoleRepository _memberRoleRepository;
public Authorization(Educ8DbContext context)
{
_dbContext = context;
_memberRepository = new MemberRepository(_dbContext);
_roleRepository = new RoleRepository(_dbContext);
_memberRoleRepository = new MemberRoleRepository(_dbContext);
}
public IQueryable<Role> GetRoles()
{
return _roleRepository.ListAll();
}
public IQueryable<Role> GetRolesForMember(int memberId)
{
var roleIds = _memberRoleRepository.ListAll()
.Where(mr => mr.MemberId == memberId)
.Select(mr => mr.RoleId);
return _roleRepository.ListAll()
.Where(r => roleIds.Contains(r.Id));
}
}
I get about two to three of the following exceptions every hour. Restarting the project immediately solves the problem, until the next one.
- Not allowed to change the 'ConnectionString' property. The connection's current state is closed.
- The context cannot be used while the model is being created.
- The underlying provider failed on Open.
It may be worth noting that I have absolutely zero data access issues anywhere else in the project.
Any suggestions on what may be causing this would be most welcome.
回答1:
Gert Arnold is on the right track with his comment. You have to realize that the RoleProvider
runs as a singleton. Each time you restart your app, it is causing a new instance of this class to be constructed. As long as your application is running, it keeps using this one single instance.
I used to get the same kinds of exceptions as in your question before I realized that this class runs as a singleton. After you have that knowledge, it is not difficult to make these exceptions go away:
public class Educ8RoleProvider : RoleProvider
{
//private readonly Educ8DbContext _dbContext = new Educ8DbContext();
//private readonly Authorization _authorization;
public Educ8RoleProvider()
{
//_authorization = new Authorization(_dbContext);
}
private Authorization GetAuthorization()
{
return new Authorization(new Educ8DbContext());
}
public override void Initialize(string name, NameValueCollection config)
{
try
{
base.Initialize(name, config);
}
catch (Exception ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
throw;
}
}
public override bool IsUserInRole(string username, string roleName)
{
return GetRolesForUser(username)
.Any(r => r.ToLower() == roleName);
}
public override string[] GetRolesForUser(string username)
{
return GetAuthorization().GetRolesForMember(username)
.Select(r => r.Name).ToArray();
}
}
Essentially, you want to make sure that each method call on the RoleProvider
works with a brand new DbContext
instance. This way, the RoleProvider
singleton is not hanging onto a single DbContext
that gets stale.
来源:https://stackoverflow.com/questions/12677975/what-could-cause-many-data-access-exceptions-using-ef-code-first-in-a-custom-rol