具有约束的EF自引用多对多

时间:2017-01-13 11:41:44

标签: c# .net entity-framework foreign-keys

我有一个自引用关系的课程。课程如下:

public class TableActivity
{

    public TableActivity()
    {
    }

    public int TableActivityID {get;set;}
    public string Table {get;set;}      
    public Activity Activity {get;set;}

    public virtual ObservableCollection<TableActivity> RelatedActivities {get;set;}
}

在我的上下文类

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TableActivity>() 
        .HasMany<TableActivity>(t => t.TableActivityID) 
        .WithMany() 
        .Map(m => 
        { 
             m.ToTable("RelatedActivities"); 
             m.MapLeftKey("TableActivityID"); 
             m.MapRightKey("RelatedTableActivityID"); 
        });

    }

我想添加2个特定约束

  1. TableActivity对象无法在RelatedActivities
  2. 中列出
  3. 例如,如果我们有2个TableActivity对象o1和o2如果o1.relatedActivities.contains(o2)那么o2.relatedActivities不能列出o1
  4. 如何实现这两个约束?

    我做了什么

    我创建了一个继承ObservableCollection的助手类,我管理了添加方法。

    public class RelatedTableActivityCollection :ObservableCollection<TableActivity>
    {
    
    
        private TableActivity m_Owner;
        public RelatedTableActivityCollection(TableActivity owner)
        {
            this.m_Owner = owner;
        }
    
        public new void Add(TableActivity item)
        {
            if (m_Owner.Equals(item)) {
                return;
            } else {
                base.Add(item);
            }
        }
    
    }
    

    此解决方案的问题在于它在应用程序上运行良好,但在数据库端没有任何操作。有没有办法让数据库考虑到这些变化?

2 个答案:

答案 0 :(得分:0)

在数据库端,您可以使用检查约束来强制执行限制。您尚未指定使用的DBMS,但在SQL Server中,第一个检查约束很简单:

alter table RelatedActivities add constraint CK_RelatedActivity check (TableActivityId <> RelatedTableActivityId)

第二个条件更复杂,因为您必须检查表中的其他条目。这是可能的,但你需要一个标量函数(使用模式绑定)。您可以从第二个检查约束中调用此函数。

您的问题是,首先使用代码,您无法轻松添加检查约束check this link以查看如何使其工作。

答案 1 :(得分:0)

在数据库方面,我强制执行两个约束(以满足要求), 第一个是@Sefe回答,第二个是使用标量函数@Sefe建议

alter table RelatedActivities add constraint CK_RelatedActivity check (TableActivityID <> RelatedTableActivitiyID)

alter table RelatedActivities add constraint CK_RelatedActivityRelation check (dbo.CheckRelatedActivities(TableActivityID,RelatedTableActivitiyID)<1)

标量函数的定义

CREATE FUNCTION [dbo].[CheckRelatedActivities](@TableActivityId int,@RelatedTableActivityId int)

RETURNS int
AS
BEGIN

    -- Declare the return variable here 
    DECLARE @Result int 
    -- Add the T-SQL statements to compute the return value here

    select @Result = count(1)
where @TableActivityId in (select RelatedTableActivitiyID from RelatedActivities where TableActivityID = @RelatedTableActivityId)


    RETURN @Result

END