代码改变世界

NHibernate in Action Ch3 PoCOs

2011-08-11 07:07  一一九九  阅读(224)  评论(0编辑  收藏  举报

         本章开始介绍了一个CaveatEmptor的例子,数据关系大体上如下所示,作者在后面介绍Mapping的时候没有具体的示例或者Step  by Step, 所以需要对这张图有所掌握,自己写出来相应的代码。

image

3.2 implementing the domain model
      
作者在这里提到当实现一个领域模型的时候需要考虑的几件事情,比如说:

  • how do you separate the business concerns from the cross-cutting concerns(such as transactions and even persistence)?
  • what kind of persistence is needed: automated or transparent?
  • do  you have to use a sepecific programming model to achieve this?

         we say that the domain model should be “concerned” only with modeling the business domain. but there are other concerns, such as persistence, transaction management, and authorization. you shouldn’t put code that addresses these cross-cutting concerns in the classes that implement the domain model . when these concerns start to appear in the domain model class, we call this an example of leakage of concerns.

      Nhibernate 之所以不存在这方面的问题(leakage  of concerns)就是因为Nhibernate offers someting that dateSets don’t :transparent persistence.

Transparent and automated persistence.

       如何理解transparent? 
       A DateSet allows you to extract the changes performed on it in order to persist them. NHibernate provides a different feature, which is sophisticated and powerful: it can automatically persist your changes in a way that is transparent to your domain model.
       
简单说的就是如果使用DataSet的话,就需要DataSet内部内置的各种Object才能完成持久化的操作,而采用NH则可以将Object和持久化的内容隔离。也可以这样理解,在DataSet下必须将业务对象转换成DataSet的Column,Row对象才行。

        we use transparent to mean a complete separation of concerns between the persistent classes of the domain model and the persistence logic itself, where the persistent classes are unaware of –and have no dependency on the persistence mchanism.

      Nhibernate的transparent主要体现在以下几方面:

  • NHibernate doesn’t require that any special base classes or interfaces be inherited or implemented by persistent classes.
  • Persistent classes may be reused outside the context of persistence- in unit tests or in the user interface tier.
  • in a system with transparent persistence , objects aren’t aware of the underlying data store; they need not even be aware that they’er being persisted or retrieved. Persistence concerns are externalized to a generic persistence manager interface.

       NHibernate 也不是完全的transparent的, every automated persistence layer, including nhibernate , impose some requirements on the persistent classes. for examle, nhibernate requires that collection-valued properties be typed to an interface such as IList or IDictionary and not to an actual implementation such as ArrayList.

Write POCOs

nhibernate 对POCO类存在一定的要求和需要。

[Serializable]
public class User{

        public User(){}

        public  string UserName{get;set};

         public Address Address{get;set;}

         public MonetaryAmount CalcShipCost(Address from){}

}

  • serializable 并不是NHibernate 要求的,但是主要用于.net  remoting.
  • 需要一个默认的无参的构造函数。
  • 需要属性。

Implimenting POCO associations

   you use properties to express associations between POCO classes, and you use accessor methods to navigate the object graph at runtime.

       NHibernate requires interfaces for collection-typed attributes.  at runtime, Nhibernate wraps the collection instance with an instance of one of Nhibernate’s own clsses.

       todo: External library: lesi.Collections 观察一下都有哪些类,这些类和c#的类的区别是什么?

      在Category类中实现自身的引用关系,可以通过以下代码进行:

public ISet ChildCategories{get;set;}
public Category ParentCategory{get;set;}

      如果想要维护两者之间的关系,也就是Object  Graph的话,需要通过以下方式来进行.

Category aParent = new Category();
Category aChild = new Category();
aChild.ParentCategory = aParent;
aParent.ChildCategories.Add(aChild);

     whenever an association is created between a parent Category and a child Category, two actions are required:

  • The parentCategory of the child must be set, effectively breaking the association between the child and its old parent(there can be only one parent for any child).
  • the child must be added to the ChildCategories collection of the new parent Category.

这个地方比较关键的理解点: 对象之间是存在一定的关系的,这种关系是从R中映射过来的,而这种关系是需要手动进行维护的,不能通过NH进行维护。

 Managed relationships in NHibernate
     
NHibernate doesn’t “manage” persistent associatons. if you want to manipulate an association,you must write exactly the same code you would write without nhibernate. if an association is bidirectional, both sides of the relationship must be considered. Anyway, this is required if you want to use your objects without NH.

A convenience metho is to the Category class that groups these operations, allowing reuse and helping ensure correctness:

public void AddChildCategory(Category childCategory){
     if ( childcategory.ParentCategory != null)
           childCategory.ParentCategory.ChildCategories.Remove(childCategory);
   childCategory.ParentCategory = this;
   childCategories.Add(childCategory);  }

  the  addchildCategory() method not only reduces the lines of code when dealing with Category objects, but also enforeces the cardinality of the association. Errors that arise from leaving out one of the two required actions are voided. this kind of grouping of operations should always be provided for associations,  if possible.

这个地方主要进行Object Graph的设计,这个地方比较繁琐的是需要在Object的双方或者某一方来维护关系,而这个关系还是非常有必要的,需要选择适当的时机来维护这种关系,可以选择在One的一方,也可以选择在多的一方,如果把Object理解成为一个Tree的形式的话,最好选择在One的一方进行维护。而在One的一方进行维护这种关系就会导致One成为了多变的一方,比如说添加个子类啥的都需要将One的一方的代码进行修改才可以。

Adding logic to properites

        这个地方说了如下的几件事情

  • Property是可以进行Set的,并且在Set的时候可以进行Validate的,而这个过程和NH结合起来之后需要考虑之前的数据库中的数据是否存在不满足条件的数据。这个可以设置为False。之前提到可以在NH这一层进行空或者非空的校验,现在看来在这一个地方就存在一个缺陷。
  • Nh是需要进行Dirty Check的,而这个Dirty Check的过程是需要将不同的对象进行Compare的,如果是属性的话则进行的是Value的Compare,而如果是Collection的话,则是进行的Object Identity的对比,所以在设置对象的Get的方法的时候一定慎重。