【问题标题】:NHibernate 3.2 mapping choices, relations and POV?NHibernate 3.2 映射选择、关系和 POV?
【发布时间】:2026-01-24 03:00:02
【问题描述】:

我正在尝试学习 NH(版本 3.2),但在理解某些映射选择时遇到了问题。 Scott Findlater 为性感 Loquacious NH here 发布了他的完整工作骨架,我关于映射的问题将基于他的示例。 这是域模型(图片不是他的示例的一部分,但为了清楚起见包括在此处):

他的类别类如下所示:

public class Category : Entity
    {
        public Category()
        {
            Products = new List<Product>();
            SubCategories = new List<Category>();
        }

        public virtual string Name { get; set; }
        public virtual string Description { get; set; }
        public virtual Category Parent { get; set; }
        public virtual IEnumerable<Category> SubCategories { get; set; }
        public virtual IList<Product> Products { get; set; }
    }

他的映射类是这样的:

class CategoryMap : ClassMapping<Category>
    {
        public CategoryMap()
        {
            // **************************************************
            // Mapping of Id here will take precedence over the 
            // global conventions configured in the ModelMapper.
            // **************************************************
            //Id(x => x.Id, map =>
            //{
            //    map.Column("Id");
            //    map.Generator(Generators.GuidComb);
            //});

            Property(x => x.Name, m => m.Length(450));
            Property(x => x.Description, m => m.Length(2000));

            Set(x => x.SubCategories, set =>
                                          {
                                              set.Key(k => k.Column("ParentCategoryId"));
                                              set.Inverse(true);
                                          } ,
                                       ce => ce.OneToMany());

            ManyToOne(x => x.Parent, manyToOne =>
                                         {
                                             manyToOne.Column("ParentCategoryId");
                                             manyToOne.Lazy(LazyRelation.NoLazy);
                                             manyToOne.NotNullable(false);
                                         });


            Set(x => x.Products, set =>
                                    {
                                        set.Key(key =>
                                        {
                                            key.Column("ProductId");
                                            key.ForeignKey("FK_Product_Category_ProductId");
                                        });
                                        set.Table("Product_Category");
                                    },
                                    ce => ce.ManyToMany(m => m.Column("CategoryId")));
        }
    }

现在,对于问题:

1) 为什么他选择将 Parent 属性映射/建模为 ManyToOne 关系?这是否表明 Category 可以属于多个父类别,即任何给定类别(我认为除了根类别之外)都可以分布在许多其他父类别中?如果是这样,那么从模型本身来看,这并不是很清楚,因为对我来说,Parent(正如我在类定义中看到的那样)看起来像 Category 类型的属性,我会这样映射它。你什么时候会在这个解决方案中选择方法?将其映射为一个简单的属性?

2) 当我映射文件时,我应该从谁(或哪个)角度查看?在我看来,这是来自您要映射的课程的内部。所以,在这种情况下,当我尝试映射 Category 类时,我只关心映射出去的“箭头”,对吧?

3) 创建映射文件的人必须具有仅通过查看类就清楚的知识之外的知识。查看 Products 属性是如何映射的(ManyToMany 关系)。从类本身来看,仅清楚 Category 可能属于许多 Products,但 Category 不知道它可能包含在许多 Products 中。对于 Product 类,这一事实是显而易见的。现在我已经说过,在我看来,当我创建映射文件时,我应该从一个类的角度来看,然后是一个模型。

4) 一般来说:什么时候使用.Inverse()、.Cascade() 和.Lazy()?

5) 使用 ModelMapper 与 ConventionModelMapper 进行映射有什么区别?我没有研究过使用后一种方法的同一个项目中包含的文件,但我想知道除了偏好之外,使用一个比另一个更有优势。

【问题讨论】:

    标签: nhibernate


    【解决方案1】:
    1. Scott 决定在类别与其父(另一个)类别之间建立Ordinary Association(many-to-one) 关联。多对一关联使您可以访问在属性映射中找不到的功能,例如级联和获取策略。例如,假设您想删除一个父级及其所有子级。级联可以帮助您。

    2. 如果您有关联,则必须考虑关联的双方。例如,假设您在 'A''B' 之间有一个双向的一对多关联,您需要注意哪一方管理该关系。当您为 'A' 编写映射时,您会考虑 'A' 的关系,反之亦然,在映射 'B'强>.

    3. 你的观点对我来说有点不清楚。但是,您似乎在描述的是基本的 OOP 对象关系。一个类可能具有属性 'A',它是与对象 'B' 的关系,而 'B' 又可能与 相关'C'。仅通过查看 'A' 无法判断它与 'C' 有传递关系。这没有什么问题。

    4. Read the documentation

      4.1 反向:定义双向关系的哪一方管理关系。

      4.2 级联:允许某些操作级联到子关联。 (例如删除)

      4.3 Lazy:定义加载集合的策略。 (急切地/懒惰地)

    5. ConventionalModelMapper 构建在 ModelMapper 之上,并提供方便的方法和默认映射约定,使按约定映射的体验更加轻松。

    【讨论】:

    • 我想当关联是双向/单向时,我在检测(查看域模型时)时遇到问题。我应该如何考虑产品和类别之间的关联?通过查看模型,我看到了两个一对多的关联——产品有很多类别,类别有很多产品。这是不正确的吗?还是我应该将其视为一个多对多关联?
    【解决方案2】:
    • 对于1. 并不是说​​每个分类有多个父分类,而是说同一个父分类中可以表示多个分类,每个分类可以有一个列表的子类别。如果表示为一对一,那就意味着每个类别只有一个类别,我认为您不是故意的。

    • 对于 4. Inverse() 用于指定关联的所有者,因此您可以在子实体不是所有者的一对多关系中使用它关系或子实体不会对关系负责,也不知道关系,因此如果设置为 true,NHibernate 将不会尝试插入或更新连接定义的属性。

    • Cascade() 指定将从父实体级联到关联实体的操作。

    • lazy 用于延迟加载其他实体引用的实体。

    • 对于 2. 和 3. 我不明白你的意思和你的意思,但我认为当你映射一个实体时,是的,你应该从你正在映射的类的角度来看当你映射关系的另一边时,同样的事情,从它的角度来看,你应该同时考虑关系的两侧。

    【讨论】: