Linq To Sql: отношения не обновлены правильно - PullRequest
4 голосов
/ 25 ноября 2010

Краткое описание проблемы:

При использовании одного и того же DataContext для вставки и обновления пользователя с отношением к ряду ролей отношения не корректно обновляются в моих классах LinqToSql (ноотлично в базе).Использование одного DataContexts для вставки и другого для обновления работает нормально.

Подробное описание:

У меня есть таблица пользователей и таблица ролей в моей базе данных.Чтобы иметь отношение «многие ко многим», у меня также есть таблица UserRoleRelation (с двумя внешними ключами для User.ID и Role.ID).

У меня есть тест, в котором создается пользователь, и две роли( A и B ) добавлены к этому пользователю.Затем я удаляю роль A , добавляю новую роль C и обновляю пользователя.

Но когда я затем выбираю пользователя в базе данных ( DataContext.Users.Where (p => p.ID.equals (user.id)). FirstOrDefault () ) тогдапользователь имеет только одну UserRoleRelation (на роль A )!Но в базе данных все в порядке - обе роли A и C связаны с пользователем.

Я использую веб-службы и, следовательно, шаблон репозитория - для каждоговызов службы Я создаю новый DataContext - однако одна и та же служба может возиться с одним и тем же объектом (например, User, UserRoleRelation или Role) более одного раза, чтобы они уже были присоединены к DataContext - поэтому, когда я присоединяю объекты к DataContext, я ловлюпотенциальные InvalidOperationExceptions (например, объект уже присоединен) и их игнорирование.

В моем тесте я использую один и тот же DataContext для вставки и обновления пользователя - однако, если я использую два разных DataContexts, то он работает нормально -пользователь правильно извлечен из базы данных!

Так что по какой-то причине кеширование внутри DataContext испортилось.

Вот мой метод UpdateUser:

private User UpdateUser(User user)
{
    foreach (UserRoleRelation relation in user.UserRoleRelations)
    {
        if (relation.Role != null)
        {
            TryAttach(DataContext.Roles, relation.Role); // same as DataContext.Roles.Attach(relation.Role)
        }
    }
    // attach the new user as modified
    TryAttach(DataContext.Users, user, true); // same as DataContext.Users.Attach(user, true), but is that the correct way to do it?

    // update the relations (figure out which are removed, added and unchanged)
    IEnumerable<UserRoleRelation> oldRelations = DataContext.UserRoleRelations.Where(p => p.UserID.Equals(user.ID)).ToList();

    // mark for deletion (those elements that are in the old list, but not in the new)
    IEnumerable<UserRoleRelation> deletionList = oldRelations.Except(user.UserRoleRelations, userRoleRelationComparer).ToList();
    DataContext.UserRoleRelations.DeleteAllOnSubmit(deletionList);

    // mark for insert (those that are in the new list, but not in the old)
    IEnumerable<UserRoleRelation> insertionList = user.UserRoleRelations.Except(oldRelations, userRoleRelationComparer).ToList();
    DataContext.UserRoleRelations.InsertAllOnSubmit(insertionList);

    // attach the rest as unmodified (those that are in both lists)
    IEnumerable<UserRoleRelation> unmodifiedList = oldRelations.Intersect(user.UserRoleRelations, userRoleRelationComparer).ToList();
    TryAttachAll(DataContext.UserRoleRelations, unmodifiedList);

    DataContext.SubmitChanges();

    // return the updated user (in order to be sure that all relations are update, we fetch the user from the DB)
    User updatedUser = GetUser(user.Email); // same as DataContext.Users.Where(p => p.Email.Equals(user.Email)).FirstOrDefault();
    return updatedUser;
}

Чтоя делаю не так?- Я почти уверен, что когда я использую тот же самый DataContext в моем тесте, «присоединение пользователя к DataContext» вызывает исключение (оно уже присоединено), и, возможно, именно поэтому я не получаю правильные отношения обратно -но LinqToSql должен уметь определять изменения в отношениях ...

1 Ответ

1 голос
/ 27 января 2011

Я думаю, что проблема не в методе Update, а здесь "DataContext.Users.Where (p => p.ID.equals (user.id)). FirstOrDefault ()", вы используете FirstorDefault () и linq возвращает только первую из записей. попробуйте удалить FirstOrDefault () и сохранить результаты в массиве ...

...