Linq To Sql:关系未正确更新
问题摘要:
使用相同的 DataContext 插入和更新与多个角色相关的用户,这些关系在我的 LinqToSql 类中未正确更新(但在数据库中正常)。使用一个 DataContext 进行插入并使用另一个 DataContext 进行更新效果很好。
详细描述:
我的数据库中有一个用户表和一个角色表。为了在它们之间建立多对多关系,我还有一个 UserRoleRelation 表(带有 User.ID 和 Role.ID 的两个外键)。
我有一个测试,其中创建了一个用户并向该用户添加了两个角色(A 和 B)。然后,我删除角色 A 并添加新角色 C 并更新用户。
但是,当我然后在数据库中选择用户时(通过 DataContext.Users.Where(p => p.ID.equals(user.id)).FirstOrDefault()),那么用户只有一个 UserRoleRelation(角色 A)!但数据库中的一切都很好 - 角色 A 和 C 都与用户相关。
我正在使用 Web 服务,因此使用存储库模式 - 对于每个服务调用,我创建一个新的 DataContext - 但是相同的服务可能会多次修改相同的对象(例如 User、UserRoleRelation 或 Role),以便它们已经附加到 DataContext - 因此,当我将对象附加到 DataContext 时,我会捕获潜在的 InvalidOperationException(例如,对象已附加)并忽略它们。
在我的测试中,我使用相同的 DataContext 来插入和更新用户 - 但是,如果我使用两个不同的 DataContext,那么它工作正常 - 从数据库中正确检索用户!
因此,由于某种原因,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 应该能够发现关系的变化......
Problem summary:
Using the same DataContext to both insert and update a User with a relation to a number of Roles, the relations are not correctly updated in my LinqToSql classes (but fine in the database). Using one DataContexts to insert and another to update works fine.
Detailed description:
I have a User table and a Role table in my Database. To have a many-to-many relationship between them I also have a UserRoleRelation table (with two foreign keys to User.ID and Role.ID).
I have a test where a user is created and two roles (A and B) are added to that user. Then I remove role A and add a new role C and update the user.
But when I then select the user in the database (by DataContext.Users.Where(p => p.ID.equals(user.id)).FirstOrDefault()) then the user only has one UserRoleRelation (to role A)! But everything is fine in the database - both role A and C are related to the user.
I am using Web Services and thus the Repository pattern - for each service call I create a new DataContext - however the same service might fiddle with same Object (e.g. User, UserRoleRelation or Role) more than once so that they are already attached to the DataContext - so when I attach objects to the DataContext, I am catching potential InvalidOperationExceptions (e.g. the object is already attached) and ignoring them.
In my test I use the same DataContext to insert and update the user - however, if I use two different DataContexts, then it works fine - the user is correctly retrieved from the Database!
So for some reason, the caching inside the DataContext is messed up.
Here is my UpdateUser method:
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;
}
What am I doing wrong? - I am pretty sure that when I use the same DataContext in my test, the "attach of the user to the DataContext" throws an exception (it is already attached), and that might be why I am not getting the correct relations back - but LinqToSql should be able to spot the change in relations...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为问题不在 Update 方法上,而是在这里“DataContext.Users.Where(p => p.ID.equals(user.id)).FirstOrDefault()”,您正在使用 FirstorDefault() 并且 linq 正在返回仅第一条记录。尝试删除 FirstOrDefault() 并将结果保存在数组中...
I think the problem is not on the Update method but here "DataContext.Users.Where(p => p.ID.equals(user.id)).FirstOrDefault()", you are using FirstorDefault() and linq is returning only the first of the records. try removing FirstOrDefault() and saving the results on an Array...