C# CodeSmith LINQ to SQL 问题 DELETE 操作
在我正在进行的一个项目中,我需要从数据库中删除一个“用户”。这个“用户”有两个引用它的外键的表。当硬删除时,我尝试删除表 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 的准备更改,它会将其放入字典中,并且不知何故,两件事的密钥是相同的,并且在更改发生之前会出错。
任何帮助将不胜感激。
In a project I am working on I need to delete a "user" from my database. This "user" has two tables that reference it's foreign key. When hard deleting I am trying to delete all records from Table A and Table B that have foreign keys to the "user" and then deleting that "user" record. This is all done within repositories and using object factory.
The code is as follows:
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());
}
If each table has one record, it works fine. If a table has multiple, which can only happen on the UserToken and UserMappings, I get the following error.
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)
I had to put in XXXX for privacy reasons. What I read this as was that however LINQ is storing preping the changes for SQL it puts it into a Dictionary, and somehow the key for two things is the same and it errors before a change occurs.
Any help would be much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我有点在黑暗中拍摄,并假设你的阅读方式是正确的,以及我一路上经历的一点痛苦。
您要删除的表是否有自己的主键,或者您是否使用外键作为主键? (好吧,你知道我的意思...听起来他们没有 linq 知道的自己独立的唯一主键)'
linq 使用 GetHash 方法从主键字段构造唯一 id .. 我是猜测这些字段重复,因此出现字典问题...问题不是由具有相同键 id 的 2 个不同表引起的。
我猜测这些包含多个项目的表是一种多对多连接的中间形式。一个快速而肮脏的修复方法是向它们添加一个自动增量列并将其分配给主键(否则尝试使用多字段 pk - 我还没有真正尝试过 linq deliberatley)。
我希望这能给您一些想法...您可以在部分类中重写 GetHashCode 以另一种方式解决您的问题...但是您应该只包含在单个项目中不变的数据部分)
I am kinda shooting in the dark here and assuming how you read it is correct along with a little pain i've had along the way.
do the tables you are deleting from have their own primary key or are you using the foreign key as the pk? (well you know what i mean ... it doesn't sound like they have their own independent unique primary key that linq is aware of)'
linq uses the GetHash method to construct a unique id from the primary key fields .. i am guessing that these fields duplicate and hence the dictionary problem ... the problem is not caused by 2 different tables having the same key id.
I am guessing that these tables with multiple items in are a kind of in the middle of a many to many join. A quick and dirty fix would be to add an auto increment column to them nd assign this to the primary key (otherwise try using a multi field pk - which i haven;t really tried out with linq deliberatley).
I hope this gives you some ideas ... you could override GetHashCode in a partial class to fix your problem another way ... however you should only include the parts of your data that are invariant accross a single item)
这是一个老问题,但是我们永远无法同时对两个表进行删除。我们的解决方案是先删除一个,然后再删除另一个,然后提交之间的更改。
This is an old question however we were never able to make this delete to both tables simultaneously. Our solution was to delete from one then the other and commit the changes in between.