2010-07-15 4 views
1

В проекте, над которым я работаю, мне нужно удалить «пользователя» из моей базы данных. Этот «пользователь» имеет две таблицы, которые ссылаются на внешний ключ. При жестком удалении я пытаюсь удалить все записи из таблицы A и таблицы B, которые имеют внешние ключи к «пользователю», а затем удаляют эту «пользовательскую» запись. Все это делается в хранилищах и с использованием фабрики объектов.C# CodeSmith LINQ to SQL question DELETE Операция

Код выглядит следующим образом:

public void RemoveUserByUserId(int userId) 
{ 
var user = m_context.User.GetByKey(userId); 

ObjectFactory.Inject(m_context); 

UserTokenRepository.RemoveUserTokensByUserId(userId); 
UserMappingRepository.RemoveUserMappingsByUserId(userId); 

m_context.User.DeleteOnSubmit(user); 

m_context.SubmitChanges(); 

ObjectFactory.ResetDefaults(); 
} 

public static void RemoveUserTokensByUserId(int userId) 
{ 
var dataContext = ObjectFactory.GetInstance<DataContext>(); 
var userTokens = dataContext.UserToken.ByUserId(userId); 
dataContext.UserToken.DeleteAllOnSubmit(userTokens.AsEnumerable()); 
} 

public static void RemoveUserMappingsByUserId(int userId) 
{ 
var dataContext = ObjectFactory.GetInstance<DataContext>(); 
var userMappings= dataContext.UserMapping.ByUserId(userId); 
dataContext.UserMapping.DeleteAllOnSubmit(userMappings.AsEnumerable()); 
} 

Если каждая таблица имеет одну запись, она отлично работает. Если таблица имеет несколько, что может произойти только в UserToken и UserMappings, я получаю следующую ошибку.

System.ArgumentException was unhandled by user code 
Message=An item with the same key has already been added. 
    Source=mscorlib 
    StackTrace: 
     at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) 
     at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) 
     at System.Data.Linq.ChangeProcessor.EdgeMap.Add(MetaAssociation assoc, TrackedObject from, TrackedObject to) 
     at System.Data.Linq.ChangeProcessor.BuildEdgeMaps() 
     at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode) 
     at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) 
     at XXXX.XXXX.XXXX.XXXXDataContext.SubmitChanges(ConflictMode failureMode) in XXXX:line 519 
     at System.Data.Linq.DataContext.SubmitChanges() 
     at XXXX.UserRepository.RemoveUserByUserId(Int32 userId) in XXXX:line 146 
     at XXXX(Int32 profileUserId) in XXXX:line 948 
     at XXXX(Int32 profileUserId) in XXXX:line 165 
     at SyncInvokeUnregisterUserForActivationFailed(Object , Object[] , Object[]) 
     at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) 
     at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) 

Мне пришлось установить XXXX по соображениям конфиденциальности. То, что я читал, так это то, что LINQ хранит предварительные изменения для SQL, он помещает его в словарь, и как-то ключ к двум вещам один и тот же, и ошибки перед тем, как произойдет изменение.

Любая помощь будет высоко оценена.

ответ

0

Это старый вопрос, однако мы никогда не могли сделать это удалением для обеих таблиц одновременно. Наше решение состояло в том, чтобы удалить из одного другого и зафиксировать изменения между ними.

0

Я вроде как стреляю в темноту здесь и предполагаю, как вы читаете, это правильно, и небольшая боль у меня была на этом пути.

делать таблицы, которые вы удаляете, иметь свой первичный ключ или использовать внешний ключ как pk? (ну, вы знаете, что я имею в виду ... это не похоже на то, что у них есть собственный независимый уникальный первичный ключ, о котором знает linq).

linq использует метод GetHash для создания уникального идентификатора из полей первичного ключа .. Я предполагаю, что эти поля дублируют и, следовательно, проблему со словарем ... проблема не вызвана двумя разными таблицами, имеющими один и тот же ключ.

Я предполагаю, что эти таблицы с несколькими элементами внутри являются своего рода посреди многих из многих. Быстрое и грязное исправление заключалось бы в том, чтобы добавить столбец автоматического приращения к ним и назначить это первичному ключу (в противном случае попробуйте использовать многопользовательское поле pk - которое я не знаю, я действительно пробовал с помощью linq mindatley).

Надеюсь, это даст вам некоторые идеи ... вы можете переопределить GetHashCode в частичном классе, чтобы исправить вашу проблему другим способом ... однако вы должны включать только части ваших данных, которые являются инвариантными по одному элементу)

+0

Фактически каждая таблица имеет первичный ключ. структура выглядит следующим образом. Таблица пользователя [pk: user_id] Таблица UserToken - [pk: token_id (guid)] [fk: user_mapping_id] [fk: user_id] Таблица UserMapping - [pk: user_mapping_id] [fk: user_id] –

Смежные вопросы