将一个建模为零或一个关系(Z基数)

Jam*_*Ide 8 oop nhibernate nhibernate-mapping

我正在努力寻找模拟1:0,1关系("可能有一个"或"最多只有一个")的最佳方式.我相信这被称为Z基数.

例如,假设我有两个类WidgetWidgetTest.并非所有小部件都经过测试且测试具有破坏性,因此每个小部件最多只能有一个WidgetTest.还假设将WidgetTest字段添加到Widget是不合适的.

我希望我的公共界面是:

Widget
    WidgetTest { get; set; }

WidgetTest
    Widget { get; }
Run Code Online (Sandbox Code Playgroud)

模型1:Widget具有WidgetTest属性,并且在数据库中Widget表具有WidgetTest的唯一约束外键.我的DBA辩称,这将允许WidgetTest记录在没有Widget的情况下存在.

WidgetTable
    WidgetTestId (FK, UQ)
Run Code Online (Sandbox Code Playgroud)

模型2:Widget具有WidgetTest的私有集合,并通过在公共WidgetTest属性控制的集合中添加或删除单个对象来强制执行0,1关系.数据库将此模型设置为1:m,WidgetTest具有对Widget唯一约束的外键.我认为这意味着采用该模型来适应数据库模式(即为我做更多的工作).

WidgetTestTable
    WidgetId (FK, UQ)
Run Code Online (Sandbox Code Playgroud)

哪种型号更好?使用NHibernate更容易实现哪些?还是有第三种方式?

编辑......这是我最终得到的结果:

public class Widget
{
    // This is mapped in NH using a access strategy
    private IList<WidgetTest> _widgetTests = new List<WidgetTest>(1);

    public WidgetTest
    {
        get { return _widgetTests.FirstOrDefault(); }
        set
        {
            _widgetTests.Clear();
            if (value != null)
            {
                _widgetTests.Add(value);
            }
         }
     }
}
Run Code Online (Sandbox Code Playgroud)

nw.*_*nw. 4

我的方法是在映射中对一对多关系进行建模,但将“多”限制为单个项目。这允许可选的一对一,并且还保证您的 WidgetTest 实例在您保存 Widget 时被持久化。例如:

public class Widget
{
    /// <summary>
    /// This property is ignored by the NHibernate mappings.
    /// </summary>
    public virtual WidgetTest WidgetTest { get; set; }

    /// <summary>
    /// For easier persistence with NHibernate, this property repackages the
    /// WidgetTest property as a list containing a single item. If an
    /// attempt is made to set this property to a list containing more than
    /// one item, an exception will be thrown. But why bother? Just use the
    /// WidgetTest property.
    /// </summary>
    public virtual IList<WidgetTest> WidgetTests
    {
        get
        {
            IList<WidgetTest> widgetTests = new List<WidgetTest>();
            if (this.WidgetTest != null)
            {
                widgetTests.Add(this.WidgetTest);
            }
            return widgetTests;
        }
        set
        {
            if (value != null && value.Count > 1)
            {
                throw new Exception("The WidgetTests collection may not contain more than one item.");
            }
            else if (value != null && value.Count == 1)
            {
                this.WidgetTest = value[0];
            }
            else
            {
                this.WidgetTest = null;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)