В нашем приложении мы используем шаблон репозитория для извлечения и сохранения данных с нашего носителя данных. Средой, которую мы выбрали, является Entity Framework 4. Это, кажется, очень чистый способ сделать что-то, и он отлично работал в 99% случаев.
Теперь мы столкнулись с проблемой. У нас есть два хранилища, как это:
public class UserRepository : IUserRepository
{
Entities dataContext = new Entities();
public User GetUser(string username)
{
return dataContext.Users.SingleOrDefault(x => x.Username == username);
}
// ... more CRUD-style methods that are not relevant to this question.
public void SaveChanges()
{
dataContext.SaveChanges();
}
}
public RoleRepository : IRoleRepository
{
Entities dataContext = new Entities();
public Role GetRole(string name)
{
return dataContext.Roles.SingleOrDefault(x => x.Name == name);
}
// ... more CRUD-style methods that are not relevant to this question.
public void SaveChanges()
{
dataContext.SaveChanges();
}
}
Пользователи и роли на самом деле имеют отношение многие ко многим в модели Entity Framework. Иногда мы хотим взять существующего пользователя и существующую роль и связать их. Обычно это будет хорошо работать, если вы сделаете короткий пример кода, подобный этому:
Entities dataContext = new Entities();
Role roleToAdd = dataContext.Roles.Single(x => x.Name == "Admin");
User user = dataContext.Users.Single(x => x.Username == "Fred");
user.Roles.Add(roleToAdd);
dataContext.SaveChanges();
Это прекрасно работает, потому что оба объекта извлекаются из одного и того же объекта контекста данных EF. Однако в нашем приложении каждый репозиторий создает свой собственный объект контекста данных. Поэтому, когда мы пытаемся сделать то же самое, что и выше, с нашей собственной архитектурой:
UserRepository userRepo = new UserRepository();
RoleRepository roleRepo = new RoleRepository();
User user = userRepo.GetUser("Fred");
Role roleToAdd = roleRepo.GetRole("Admin");
user.Roles.Add(roleToAdd);
userRepo.SaveChanges();
Мы получаем эту ошибку:
Невозможно определить отношения между двумя объектами, поскольку они привязаны к разным объектам ObjectContext.
Каков наилучший способ централизовать этот контекст данных? Очевидно, я не хочу дублировать метод GetRole в UserRepository, потому что это было бы излишним и глупым. Я мог бы просто сделать более подробный метод в UserRepository, который принимает имя пользователя и имя пользователя, а затем использует тот же контекст данных для их извлечения и связывания, например:
public void AddUserToRole(string username, string role)
{
User user = dataContext.Users.Single(x => x.Username == username);
Role roleToAdd = dataContext.Roles.Single(x => x.Name == role);
user.Roles.Add(roleToAdd);
}
Тогда я мог бы просто сделать:
userRepo.AddUserToRole("Fred", "Admin");
userRepo.SaveChanges();
Но разве это лучший способ сделать это? Есть ли лучший способ централизовать контекст данных EF для каждого запроса, чтобы все хранилища использовали один и тот же вместо создания своего собственного? Если да, то как бы я это сделал?