Fluent Nhibernate多对多关系/依赖层次结构

时间:2012-03-05 14:58:32

标签: c# nhibernate fluent-nhibernate

我正在尝试创建一个显示事件依赖关系的测试应用程序:即生成的依赖关系图(而不仅仅是树图)。类似的东西:

public class Event() {
    public virtual int Id {get;set;}
    public virtual IList<Event> Dependencies {get;set;}
}

另一个要求是我能够在两个方向上遍历图形:给定任何一个事件,我可以使用Nhibernate访问其依赖项及其先决条件。

许多事件可能依赖于一个事件发生......但任何给定事件也可能依赖于许多其他事件。 该模型应该是什么样的(或者这需要多个模型)?如何使用Fluent NHibernate进行映射?是否有配置/映射可以防止循环引用?

2 个答案:

答案 0 :(得分:0)

我们做了类似的事情,其映射的方式是依赖事件应该有一个映射到父事件的列。这将创建必要的父/子关系,使映射有效并阻止某种循环引用。我们通过代码映射切换到NH 3.2,所以我的流利可能有点粗制滥造但是我最好的猜测:

public class EventMap : ClassMap<Event>
{
    public EventMap()
    {
       //the normal ID and property stuff

       References(x => x.ParentEvent).Column("ParentEventId");

       HasMany(x => x.Dependencies).KeyColumn("ParentEventId");
    }
}

编辑:

抱歉 - 没看到你想要一个HasManyToMany。这可能看起来像:

public class EventMap : ClassMap<Event>
    {
        public EventMap()
        {
           //the normal ID and property stuff

           HasManyToMany(x => x.Dependencies).Table("EventDependentEvent").AsBag();
        }
    }

这应该会映射您需要的链接表。你需要自己防范一些“循环” - 也就是说,在你的业务逻辑中确保你不能创建一个循环或某种大规模的对象图依赖问题。

答案 1 :(得分:0)

我最终得到的解决方案(到目前为止)......

在模型中:

    public virtual IList<Event> Dependencies{ get; set; }
    public virtual IList<Event> Prerequisites{ get; set; }

在Mapping:

        HasManyToMany(x => x.Dependencies)
            .Table("Dependencies")
            .ChildKeyColumn("Dependent");
        HasManyToMany(x => x.Prerequisites)
            .Table("Prerequisites")
            .ChildKeyColumn("Prerequisite");

我通过寻找错误来阻止循环参考:

    private bool IsPrerequisiteEvent(Event dependent, Event prereq)
    {
        bool isPrereq = false;
        if (prereq == null)
            isPrereq = false;
        else if (dependent.Id == prereq.Id)
            isPrereq = true;
        else 
        {
            int i = 0;
            while (!isPrereq && i < dependent.PrerequisiteEvents.Count)
            {
                isPrereq |= IsPrerequisiteEvent(dependent.PrerequisiteEvents[i], prereq);
                i++;
            }
        }
        return isPrereq;
    }

    private bool IsDependentEvent(Event prereq, Event dependent)
    {
        bool isDependent = false;
        if (prereq == null)
            isDependent = false;
        else if (dependent.Id == prereq.Id)
            isDependent = true;
        else
        {
            int i = 0;
            while (!isDependent && i < dependent.DependentEvents.Count)
            {
                isDependent |= IsDependentEvent(prereq, dependent.DependentEvents[i]);
                i++;
            }
        }
        return isDependent;
    }

这种方法存在权衡:db IS非规范化,但我不必创建新的依赖项对象,并为每个票证填充依赖/先决条件票据列表,然后进行检查。现在似乎更容易以这种方式编码。尽管可以接受建议!