实体框架多对8关系?

时间:2011-10-18 18:56:54

标签: c# sql entity-framework

这可能是一个比实体框架更广泛的SQL主题,我在这两个领域都是一个新手,但我会从实体框架的角度来问它。

我想强制执行多到八的关系。我的设置是:

  • PersonGroup需要8个(唯一)人员。
  • 一个人可以在许多不同的人员组中。
  • PersonGroup的顺序很重要(第一个需要先保留,等等)。
  • 轻松访问PersonGroup中的所有人以及Person所在的所有PersonGroup。

我尝试了以下内容:

1)在Person和PersonGroup之间添加8个1..many关联。使用此解决方案,每组不能超过8个人。但是,为了找到一个人所在的所有组,我需要在Person字段中迭代8个变量,这很笨重。

2)向PersonGroup添加8个与人匹配的ID。再一次,我可以保证每组只有8个人,但没有自动链接通过Person-&gt的关联; PersonGroup。我现在需要确保将它添加到两个地方。

3)只需做很多很多关系并在代码中处理它。这有两个问题:我不能保证每组只有8个人,我不确定我是否可以保证订单保持不变。

那么,哪个是最好的,或者我错过了什么解决方案?

2 个答案:

答案 0 :(得分:3)

多对多对我来说似乎没问题。通过实施触发器,您可以轻松确保每组不超过8人。此外,如果您认为它对您的逻辑很重要,您可以在此表中添加订单列。

答案 1 :(得分:3)

与“catch”的n:m关系:

Person
------
PersonId
PRIMARY KEY (PersonId)


PersonGroup
-----------
GroupId
PRIMARY KEY (GroupId)


Belongs
-------
GroupId
PersonId
Ordering

PRIMARY KEY (GroupId, PersonId)
FOREIGN KEY (GroupId)
  REFERENCES PersonGroup (GroupId)
FOREIGN KEY (PersonId)
  REFERENCES Person (PersonId)               --- all normal up to here

UNIQUE KEY (GroupId, Ordering)               --- the "catch"
CONSTRAINT Ordering_chk                      --- ensuring only up to 8 persons 
  CHECK Ordering IN (1,2,3,4,5,6,7,8)        --- per group

你应该确保你将使用的SQL引擎中有CHECK约束(例如,MySQL会诱使你相信它有这样的约束,但它只是忽略它们.SQL-Server不会返回如果您尝试插入一个错误,但很高兴在已选中的列中添加NULL。)

这种方法存在局限性。 Ordering字段必须为NOT NULL,因为如果它是NULL,则可以插入超过8行(其中为NULL)(SQL-Server除外,这样只允许最多9行,8个带值,1个带NULL。)

要确保Ordering中最多8行和NULL,您可以制作更复杂的约束,如MSDN site, CHECK Constraints中描述的约束(如果您的RDBMS具有此类功能),但我不在对这样一个野兽的表现一定肯定:

CREATE FUNCTION CheckMax8PersonPerGroup()
RETURNS int
AS 
BEGIN
   DECLARE @retval int
   SELECT @retval = CASE WHEN EXISTS
                              ( SELECT * 
                                FROM Belongs
                                GROUP BY GroupId
                                HAVING COUNT(*) > 8
                              )
                         THEN 0
                         ELSE 1
                    END 
   RETURN @retval
END;
GO
ALTER TABLE Belongs
ADD CONSTRAINT Ordering_chk 
      CHECK (CheckMax8PersonPerGroup() = 1 );
GO

也可以将约束创建为FOREIGN KEY到具有8行的引用表。 (如果你使用MySQL,这是相当于CHECK的唯一方法。)


变体是使用(GroupId, Ordering)作为主键,而不对(GroupId, PersonId)组合有任何约束。这将允许PersonGroup中有多个位置(但仍然最多为8)。