【问题标题】:Updating Many-to-Many relationship with LinqToSQL使用 LinqToSQL 更新多对多关系
【发布时间】:2010-04-10 21:19:46
【问题描述】:

例如,如果我在用户和角色表之间有一个名为“RolesToUsers”的多对多映射表,我就是这样做的:

// DataContext is db, usr is a User entity
// newUserRolesMappings is a collection with the desired new mappings, probably 
//   derived by looking at selections in a checkbox list of Roles on a User Edit page
db.RolesToUsers.DeleteAllOnSubmit(usr.RolesToUsers);
usr.RolesToUsers.Clear();
usr.RolesToUsers.AddRange(newUserRolesMappings);

我曾经使用过 SQL 分析器,这似乎生成了非常智能的 SQL - 它只会删除不再存在于映射关系中的行,并且只会添加关系中不存在的行。它不会像我想的那样盲目地彻底清理和重建关系。

互联网在这个问题上出奇地安静,查询“LinqToSQL 多对多”大多只是出现关于 LinqToSQL 数据映射器如何不能很好地“支持”它的文章。

其他人如何使用 LinqToSQL 更新多对多?

【问题讨论】:

  • 从技术上讲,这实际上并不是多对多的 ORM 等价物,因为您要手动清除连接表。 ORM 中对 m2m 的“适当”支持会将 User 对象建模为具有名为“Roles”的属性(或集合),因此,ORM 将负责在后台编辑连接表。
  • 至少这是我的解释.. HIH
  • @RobS:同意。这也是我的解释:如果您只关心一个特定用户,您可以查看“用户”对象“角色”集合。如果您关心一个特定角色,请分别查看“角色”对象“用户”集合。这就是 ORM 的想法,隐藏数据库的东西,并像使用对象一样使用它。

标签: .net linq-to-sql many-to-many


【解决方案1】:

关系是一组事实。 UsersRolesUsersToRoles 都是关系,将一个比另一个更“一流”是没有逻辑意义的。你正在做的事情很有意义,这就是为什么它看起来工作得这么好。

ORM 世界对关系模型的破坏甚至比 SQL 还要糟糕。特别是,它使关系数据库存储对象集合的谬误制度化。他们没有;它们存储一组事实。其中许多事实是关于实体的,这就是谬误如此诱人的原因。但大量事实与许多其他类型的概念有关,例如成员资格、事件、状态、意见、交易、变化、比较、历史等等。

同时考虑:

  1. 在某些时候,您可能希望指出用户何时采用了某个角色,然后可能需要指明该角色是等待批准还是暂时撤销。我发现,我想在数据模型中表达的几乎所有“关系”最终都会携带超过构成多对多关系的两个外键的有效负载。如果您的 OR 映射已设置为隐藏多对多(他们往往会这样做),那么您会发现在代码损坏方面转换到实体非常痛苦。
  2. 通常关系比二元关系更复杂。 “P教授在C班使用教科书T。”可能是一种不可约的三元关系,不容易隐藏在教授对象的某些集合属性后面。
    • 我刚刚注意到,正是这个问题在几分钟前以SO question 的形式出现。从问题来看,JPA 2.0 必须明确添加对三元关系的支持(它是否处理四元等关系?)。

【讨论】:

  • 当然对他有用,但是您不认为您应该获取一个用户对象并更新其角色集合,并让 ORM 执行连接表逻辑吗?至少他使用了 ORM,为什么他不应该从它的特性中受益呢?
  • 您对数据库级别的关系是正确的,但是当涉及到架构上方(或外部)的抽象/层时,我不同意 - UsersToRoles 表在任何上下文之外都是无用的,您自己查询该表的可能性有多大?
  • @RobS,很有可能。首先,请注意我上面的两点。其次,可以自行查询 UsersToRoles 以构建聚合,例如每个角色的用户数,或直方图类型的查询,例如有多少用户拥有五个以上的角色,甚至有多少用户共享三个以上的角色。最后一个问题在典型的 ORM 中很难回答。
  • @phild,不,我没有。一旦UsersToRoles 具有附加属性(这种情况经常发生),旧模型就会中断,您必须重新编写一堆代码。让 ORM 以这种方式隐藏事实会导致痛苦。
  • @Marcelo Cantos:+1 你完全正确。我不得不回忆一下我之前的陈述......顺便说一句,你的两个例子非常具有示范性。
【解决方案2】:

这可能不是您问题的答案,而是解释为什么“互联网在这个问题上出奇地安静”:我猜大多数人(包括我)只是更新/删除/添加 单个 n 对 n 关系的项目,因此不必问自己你的问题。

就像当您有两个表“用户”和“角色”时,用例只是向用户添加/删除角色。

只是好奇:您需要在哪个应用程序中更新整个映射,就像您的示例一样?

【讨论】:

  • 我有几个我们使用的应用程序示例,但我会使用这个:我们有 User、Roles、RolesToUsers 设置,就像原始问题的示例一样。要编辑用户所在的角色,管理控制台的“用户编辑”页面上有一个复选框列表。每个复选框代表一个角色。因此,无论用户之前的角色是什么,当管理员按“提交”编辑用户时,我都会得到一个新的角色列表(来自复选框),管理员希望用户加入。
  • 现在我很好奇。这在 LinqToSQL 中是什么样的(假设这是您使用的)?您的意思是说您已经知道要删除的 n 对 n 映射表行的 ID(当那是操作时)?并且在进行添加时,您总是只是在 n 对 n 关系中添加一行?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-30
  • 2021-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多