NHibernate 3.2映射选择,关系和POV?

时间:2011-10-24 23:46:51

标签: nhibernate

我正在尝试学习NH(版本3.2)并且在理解某些映射选择时遇到了问题。斯科特Findlater已经发布了他的性感Loquacious NH here完全工作的骨架,我关于贴图的问题将基于他的样本。 这是域模型(图片不是他的样本的一部分,但为了清楚起见包括在这里):

enter image description 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关系?这是否表明类别可以属于多个父类别,即任何给定的类别(我认为除根之外)可以分散在许多其他父类别中?如果是这样,那么从模型本身就不是很清楚了,因为对我来说,Parent(我在类定义中看到它)看起来像是Category类型的属性,我会像那样映射它。你什么时候选择在这个解决方案中的方法vs.s.将其映射为简单属性?

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

3)创建映射文件的人必须通过查看类才能掌握清晰的知识。查看Products属性的映射方式(ManyToMany关系)。从类本身来看,很明显Category可能属于许多产品,但Category不知道它可能包含在许多产品中。这一事实对于Product类来说是显而易见的。现在我已经说过,在我看来,当我创建映射文件时,我应该从类的角度来看,然后是模型。

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

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

2 个答案:

答案 0 :(得分:3)

  1. Scott决定在类别及其父级(另一个)类别之间建立Ordinary Association(many-to-one)关联。通过多对一关联,您可以访问在属性映射中找不到的级联和提取策略等功能。例如,假设您要删除父项及其所有子项。 Cascades可以帮助你。

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

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

  4. Read the documentation

    4.1 Inverse:定义双向关系的哪一侧管理关系。

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

    4.3 Lazy:定义加载集合的策略。 (热切/懒洋洋)

  5. ConventionalModelMapper构建于ModelMapper之上,提供便捷方法和默认映射约定,使常规映射体验更容易。

答案 1 :(得分:1)

  • 对于 1。这并不意味着每个类别都有多个父类别,这意味着许多类别可能表示在同一个父类别中,每个类别可以有一个列表子类别。如果它被表达为一对一,那就意味着每个类别只有一个类别,我认为你并不是故意这样做。

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

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

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

  • 对于2.和3.我无法理解你的意思和你的意思,但我认为当你映射一个实体时,你应该从你正在映射的类的角度来看,当您进行映射时,对于关系的另一方来说,同样的事情,从它的角度来看,同时你应该考虑关系的两个方面。