I have a small webapp that uses EntityFramework to store stuff via repositories into the database.
What I’ve done so far (based on all the tutorials I read) is create a repository where I need it, as shown below:
In CustomMembershipProvider:
public CustomMembershipProvider()
{
_userRepository = new UserRepository(new TenantApplicationContext());
}
In my RegisterController:
public TenantRepository TenantRepository { get; set; }
public UserRepository UserRepository { get; set; }
protected override void Initialize(RequestContext requestContext)
{
if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
if (TenantRepository == null) { TenantRepository = new TenantRepository(TenantApplicationContext); }
if (UserRepository == null) { UserRepository = new UserRepository(TenantApplicationContext); }
base.Initialize(requestContext);
}
The point is, that I instantiate the UserRepository twice. This becomes a problem when I create a User in one instance, and try to retrieve it in the other instance, and I did not call SaveChanges in between.
The problem lies here:
// Snippet from the register controller class
if (!UserRepository.Exists(model.AccountableEmailAddress))
{
// 1 - Create the user via a custom MembershipProvider
// Note, the CustomMembershipProvider has it's own instance of UserRepository
var createStatus = MembershipService.CreateUser(
model.AccountableUser,
model.Password,
model.AccountableEmailAddress);
if (createStatus == MembershipCreateStatus.Success)
{
// Left out irrelevant code
AdministerUserAndTenant(tenant.Name, model.AccountableEmailAddress);
}
}
private void AdministerUserAndTenant(string tenantName, string emailAddress)
{
// 2 - Try to retrieve the user from a different (!) instance of UserRepository
var user = UserRepository.GetUser(emailAddress);
var tenant = TenantRepository.GetTenantByName(tenantName);
tenant.Users.Add(user);
TenantApplicationContext.SaveChanges();
}
I hope you can still follow, tried to leave out unnecessary parts.
What is the best way to deal with issues like this?
PS: I’m not very fond of the Singleton pattern, so if possible don’t go there :).
When exactly does it become a problem? Cause that’s where the answer lies. Classes that should know of each other’s unsaved changes should use the same repository instance. Since they are probably related, you’ll manage passing a reference between them.
If there’s reason why all of your application should have one single repository, use Dependency Injection.