У меня проблема с сохранением изменений в базе данных, я использую отображение LINQ2SQL. Я реализовал отношение M: M (User <= UserRole => Role) на основе учебника: http://www.codeproject.com/KB/linq/linqtutorial2.aspx#premain25
Все отлично работает, когда я использую один класс, который наследуется от DataContext и отвечает за все мои классы домена, например:
[База данных]
открытый класс BookCatalog: DataContext
{
// Создать статический DataContext для удаления записей M: M Join
приватный статический DataContext contextForRemovedRecords = null;
public BookCatalog() : base("Data Source=KO2\\SQLSERVER;Initial Catalog=Katalog;Integrated Security=True") { }
public Table<User> Users;
public Table<Role> Roles;
public Table<UserRole> UserRoles;
public static void RemoveRecord<T>(T recordToRemove) where T : class
{
// Use the static contextForRemovedRecords
if (contextForRemovedRecords == null)
contextForRemovedRecords = new BookCatalog();
Table<T> tableData = contextForRemovedRecords.GetTable<T>();
var deleteRecord = tableData.SingleOrDefault(record => record == recordToRemove);
if (deleteRecord != null)
{
tableData.DeleteOnSubmit(deleteRecord);
}
}
// NEW method (not part of LINQ to SQL) to cancel changes
public void CancelChanges()
{
if (contextForRemovedRecords != null)
{
contextForRemovedRecords = null;
}
}
// Override DataContext's SubmitChanges() to handle any removed records
public new void SubmitChanges()
{
if (contextForRemovedRecords != null)
{
contextForRemovedRecords.SubmitChanges();
}
base.SubmitChanges();
}
}
К сожалению, по некоторым причинам мне нужно хранить отдельные репозитории в моем проекте. Один из них пример:
открытый класс SqlRolesRepository: IRolesRepository
{
private Table<Role> rolesTable;
public SqlRolesRepository(string connectionString)
{
rolesTable = (new DataContext(connectionString)).GetTable<Role>();
}
public IQueryable<Role> Roles
{
get { return rolesTable; }
}
public void SaveRole(Role role)
{
bool ins = false;
if (rolesTable.Any(m => m.RoleID == role.RoleID))
{
rolesTable.Context.Refresh(RefreshMode.KeepCurrentValues, role);
}
else
{
try { rolesTable.InsertOnSubmit(role); ins = true; }
catch (Exception ex)
{
throw ex;
}
}
try
{
rolesTable.Context.SubmitChanges();
}
catch (SqlException ex)
{
if (ins) rolesTable.DeleteOnSubmit(role);
List<ErrorInfo> errors = new List<ErrorInfo>();
if (ex.Message.Contains("UNQ_RoleName"))
errors.Add(new ErrorInfo("RoleName", "Rola o takiej nazwie już istnieje", role));
if (errors.Any()) throw new RulesException(errors);
throw;
}
}
public void SaveChanges()
{
rolesTable.Context.Refresh(RefreshMode.OverwriteCurrentValues);
rolesTable.Context.SubmitChanges();
}
public void DeleteRole(Role role)
{
rolesTable.DeleteOnSubmit(role);
rolesTable.Context.SubmitChanges();
}
public void DeleteRole(string roleName)
{
rolesTable.DeleteOnSubmit(rolesTable.FirstOrDefault(m => m.Name == roleName));
rolesTable.Context.SubmitChanges();
}
public Role GetRoleByName(string name)
{
return rolesTable.Single(m => m.Name == name);
}
public string[] GetAllRoles(){
return (from rola in rolesTable
select rola.Name).ToArray();
}
}
Дело в том, что когда я пытаюсь сохранить изменения:
(...)
foreach (string roleName in roleNames)
{
Role rola = _RolesRepository.GetRoleByName(roleName);
if (rola != null)
{
foreach (string userName in usernames)
{
User usr = _UsersRepository.GetUserByName(userName);
if (usr != null)
{
if (!rola.Users.Contains(usr))
{
rola.Users.Add(usr);
}
}
}
_RolesRepository.SaveChanges();
}
}
(...)
Вместо сохранения экземпляра класса ассоциации (UserRole) LINQ пытается сохранить экземпляр класса User еще раз, появляется ошибка SqlExcepiton (уникальный ключ в столбце имени пользователя). В режиме отладки я заметил, что пользовательские экземпляры как-то удвоились ...
Мои классы LINQ отображаются как в учебнике (ссылка указана выше), пример проекта доступен здесь: http://www.codeproject.com/KB/linq/linqtutorial2/linqtutorial2_src.zip
Может быть, у кого-нибудь возникнет идея, как использовать его с шаблоном репозитория (несколько репозиториев). Я читаю статью MSDN (http://msdn.microsoft.com/en-us/library/bb425822.aspx), и кажется, что вызов SubmitChanges () из моего SqlRolesRepository должен правильно обновить базу данных, но это не ...