【问题标题】:nhibernate one-to-one mapping and not-null="false"?nhibernate 一对一映射和 not-null="false"?
【发布时间】:2013-09-29 13:36:07
【问题描述】:

如何使用 NHibernate 创建一对一关系,而另一端可能为 NULL? 例如,我有一个 Banner 实体,它与 Image 实体有如下关系:

<class name="Banner" table="Banner">
    <id name="Id" type="Int64" unsaved-value="0">
        <generator class="native" />
    </id>

    <many-to-one name="Image" unique="true" column="ImageId" not-null="false"/>

    <!-- check: In the example this property was without inverse attribute -->
    <set name ="BannerSlideSet" fetch="subselect" inverse="true">
        <key column="Banner_ID" foreign-key="FK_Banner_BannerSlide" not-null="false" />
        <one-to-many class="BannerSlide"/>
    </set>
</class>

因此,对于 Banner 实体,Image 可以为空。 我创建了一个没有图像的横幅实体,没有任何问题。 在数据库中我有

--------------
ID  | ImageId
--------------
 1  | NULL

之后,我尝试创建第二个不带图像的 Banner 实例,但出现以下错误:

NHibernate.Exceptions.GenericADOException:无法插入: [Domain.Entities.Banner][SQL: INSERT INTO Banner (ImageId) VALUES (?); 选择 SCOPE_IDENTITY()] ---> System.Data.SqlClient.SqlException: 违反 UNIQUE KEY 约束“UQ_横幅_7516F70DE6141471”。 无法在对象“dbo.Banner”中插入重复键。重复键 值为 ()。

我想,这是因为我对横幅和图像实体之间的一对多关系有唯一约束,并且几个横幅实例在 ImageId 字段中不能有多个 NULL 值。问题:如何在 NHinerbate 中实现一对空的关系?

谢谢!

【问题讨论】:

    标签: c# .net nhibernate


    【解决方案1】:

    解决方案是将ImageId 移到Banner 表中。并将其放在Image 表中。

    这样,只要我们有真实(非空)图像,我们就可以让:

    1. 引用Banner (BannerId) by Image (many-to-one from Image side, and collection one-to-many of images from the Banner 侧)或
    2. 使用真正的one-to-one 关系:ImageId 是唯一受约束的,由拥有Banner 的BannerId 生成。

    这是示例来自文档5.1.11. one-to-one,调整为横幅和图像

    现在我们必须确保 BANNER 中相关行的主键 和 IMAGE 表是相等的。我们使用一个特殊的 NHibernate 标识符 生成策略叫foreign:

    图像映射:

    <class name="Image" table="[Image]">
        <id name="Id" column="[ImageId]">
            <generator class="foreign">
                <param name="property">Banner</param>
            </generator>
        </id>
        ...
        <one-to-one name="Banner" class="Banner" constrained="true"/>
    </class>
    

    横幅:

     <one-to-one name="Image" class="Image"/>
    

    【讨论】:

    • 如果图像可以在许多横幅之间共享,让我们使用配对tabler BannerImage。这将再次允许我们有没有图像的横幅,如果有关系......我们可以添加一对记录。查看&lt;bag&gt;&lt;many-to-many&gt; 映射:nhforge.org/doc/nh/en/index.html#collections-ofvalues
    • 感谢您的回复。在您的方法中,图像仅属于横幅实体。我在最初的消息中没有提到这一点,但是,我有几个引用图像的实体:Banner.Image(可空)、BannerSlide.Image(可空)、UserProfile.Photo(非空),也许还有其他。我希望可以保持与 Image 实体的单向关系(Image 可能只知道 UserProfile,因为所有用户的图像都收集在 UserProfule.Images 下)。我应该重新设计我的域结构吗?或者,也许可以用“链接”实体/表(如 Banner_Image 表)来扩展它?
    • 这里的重点是SQL Schema,有问题。不在您的实体中,不在 NHibernate 中。如果列 ImageId... 存在唯一约束,则不允许 2 个横幅具有 NULL 值。事实上,最简单的方法是删除那个约束。如果这不能满足您的要求,我认为像:Entity1-ImageEntity2-ImageEntity3-Image... 这样的配对表会为您提供最好的服务。 NHibernate 已准备好支持任何这些解决方案。享受这个工具;)
    • 再次感谢您的回复。因此,在配对表和多对多的情况下,我们有一组图像而不是 Banner.Image 属性,我们无法将其限制为 DAL 中的一个图像。而且,在服务层中,我必须确保横幅只能有一个图像。这是正确的吗?
    • 正确答案是肯定的,你必须在代码中做这些检查。另一方面,因为映射将在 C# 中表示为IList&lt;Image&gt;,即使以某种方式数据将包含更多关系......代码也将起作用。但应用这些检查的最佳位置肯定是业务/服务层
    猜你喜欢
    • 2011-06-14
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    相关资源
    最近更新 更多