2010-04-10 58 views
2

如果我有,例如,多到许多称为用户和角色表之间的“RolesToUsers”映射表,这里是我如何做到这一点:更新许多到许多与LinqToSQL关系

// 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更新多对多?

+2

从技术上讲,这不是一个真正的ORM相当于多到很多,因为你是手动清除连接表的。对ORM中m2m的“正确”支持可以将User对象建模为具有名为“Roles”的属性(或集合),因此,ORM将负责编辑封面下的连接表。 – RobS 2010-04-10 12:12:51

+0

至少这是我的解释无论如何.. HIH – RobS 2010-04-10 12:14:41

+1

@ RobS:同意。这也是我的解释:如果你只关心一个特定的用户,你看看'用户'对象'角色'集合。如果您关心某个特定角色,则分别查看“角色”对象的“用户”集合。那是一个ORM的想法,隐藏数据库的东西,并像你一样使用它只使用对象。 – 2010-04-10 12:25:49

回答

2

关系是一组事实。 Users,RolesUsersToRoles都是关系,把它看作更“一流”而不是另一个。你所做的事情是非常有意义的,这就是为什么它似乎很好地工作。

ORM世界屠杀关系模型甚至比SQL更差。特别是,它将制度化关系数据库存储对象集合的谬误。他们没有;他们存储一系列事实。其中很多事实是实体,这就是为什么谬误如此诱人。但大量的事实是关于许多其他类型的概念,例如成员资格,事件,状态,意见,交易,变化,比较,历史等等。

还认为:

  1. 在某些时候,你可能想表明,当用户采用了一定的作用,然后也许是否该角色处于待审批状态,或暂时吊销。我发现,我想在数据模型中表达的所有“关系”最终都要承载超过构成多对多关系的两个外键的有效载荷。如果你的OR映射已经设置为隐藏多对多(就像他们倾向于做的那样),你会发现从代码中断到转换到一个实体是相当痛苦的。
  2. 关系比二元关系更复杂。 “P教授在C班使用课本T.”可能是一种不可简化的三元关系,不容易隐藏在教授对象的某些集合属性后面。
    • 我刚刚注意到,恰好这个问题在几分钟前弹出为SO question。从这个问题看来,JPA 2.0必须明确加入对三元关系的支持(是否处理四元关系?)。
+1

当然,它适用于他,但你不觉得你应该更喜欢获取一个用户对象并更新其角色集合,并让ORM执行连接表逻辑?至少他使用了ORM,为什么他不应该从它的功能中受益呢? – 2010-04-10 12:43:12

+0

你对数据库级别的关系是正确的,但是当涉及模式上方(或外部)的抽象/层时,我不同意 - UsersToRoles表在任何上下文之外都没有用处,你有多大可能查询只是表格本身? – RobS 2010-04-10 12:46:06

+0

@RobS,这很可能。首先,请注意我上面的两点。其次,可以自行查询UsersToRoles来构建聚合,例如每个角色的用户数量,或者直方图类型的查询,例如有多少用户拥有五个以上角色,甚至有多少用户共享超过三个角色。最后一个问题在典型的ORM中很难回答。 – 2010-04-10 12:51:36

1

这可能不是你的问题的答案,但解释为什么'互联网在这个问题上令人惊讶的安静':我想大多数人(包括我)只是更新/删除/添加项目的一个n一对一的关系,因此从来不必自问你自己的问题。

就像当你有两个表'用户'和'角色',并且用例只是向/从用户添加/删除一个角色时。

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

+0

我有几个我们使用的应用程序的例子,但我会使用这个例子: 我们有用户,角色,RolesToUsers设置就像原始问题的例子。为了编辑用户所在的角色,管理控制台的用户编辑页面上有一个复选框列表。每个复选框代表一个角色。因此,无论用户在之前担任什么角色,当管理员按下“提交”编辑用户时,我都会得到一个新的管理员希望用户所在的角色列表(从复选框中)。 – 2010-04-12 12:11:10

+0

现在我很好奇。在LinqToSQL中看起来像什么(假设这是你使用的)?你的意思是说你已经知道你正在删除的n对n映射表行的ID(何时是操作)?而且在做一个添加时,你总是只是增加一行到n对n的关系? – 2010-04-12 12:29:08