C # CodeSmith LINQ to SQL вопрос УДАЛИТЬ Операция - PullRequest
1 голос
/ 15 июля 2010

В проекте, над которым я работаю, мне нужно удалить «пользователя» из моей базы данных.У этого «пользователя» есть две таблицы, которые ссылаются на его внешний ключ.При жестком удалении я пытаюсь удалить все записи из таблицы A и таблицы B, имеющие внешние ключи для «пользователя», а затем удаляю эту «пользовательскую» запись.Все это делается в репозиториях и с использованием фабрики объектов.

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

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, он помещает его в словарь, и почему-то ключ к двум вещам одинаков, и он ошибается до того, как произойдет изменение.

Любая помощьочень цениться.

Ответы [ 2 ]

0 голосов
/ 17 февраля 2012

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

0 голосов
/ 15 июля 2010

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

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

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

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

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

...