• NHibernate的关联映射(onetoone,onetomany,manytomany)以及cascade分析


    一、典型设置

    cascade:(默认为none)级联。指明哪些操作会从对象级联到关联的对象。

    inverse: (默认为false) 标记这个集合作为双向关联关系中的方向一端。在双向关联时才需要设置。在设为false的一端对cascade进行维护。处于性能的考虑,一般在数据少的 一端或者被依赖端设置inverse="true",而让数据多的一段维护cascade。

    1.one-to-one

    1.1 数据库表结构

    其中T_Person为主表,T_Employee为子表。T_Employee的PersonId参照T_Peson的PersonId。

    1.2 示例映射类文件

    /*
    /*作者:DDL
    /*联系:
    http://renrenqq.cnblogs.com/
    */


    using System;

    namespace DDLLY.TestNHibernate.TestAssociation.OneToOne
    {
        
    /// <summary>
        
    ///    
        
    /// </summary>

        [Serializable]
        
    public class Person
        
    {
            
    Private Members Private Members

            
    private bool _isChanged;
            
    private bool _isDeleted;
            
    private int _personid;
            
    private string _name;
            
    private Employee _employee;

            
    #endregion


            
    Default ( Empty ) Class Constuctor Default ( Empty ) Class Constuctor

            
    /// <summary>
            
    /// default constructor
            
    /// </summary>

            public Person()
            
    {
                _personid 
    = 0;
                _name 
    = null;
                _employee 
    = null;
            }


            
    #endregion
     // End of Default ( Empty ) Class Constuctor

            
    Public Properties Public Properties

            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual int PersonId
            
    {
                
    get return _personid; }
                
    set
                
    {
                    _isChanged 
    |= (_personid != value);
                    _personid 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string Name
            
    {
                
    get return _name; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 64)
                            
    throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());

                    _isChanged 
    |= (_name != value);
                    _name 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>

            public Employee Employee
            
    {
                
    get return _employee; }
                
    set { _employee = value; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsChanged
            
    {
                
    get return _isChanged; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsDeleted
            
    {
                
    get return _isDeleted; }
            }


            
    #endregion

            
    Public Functions Public Functions

            
    /// <summary>
            
    /// mark the item as deleted
            
    /// </summary>

            public void MarkAsDeleted()
            
    {
                _isDeleted 
    = true;
                _isChanged 
    = true;
            }


            
    #endregion

            
    Equals And HashCode Overrides Equals And HashCode Overrides

            
    /// <summary>
            
    /// local implementation of Equals based on unique value members
            
    /// </summary>

            public override bool Equals(object obj)
            
    {
                
    if (this == obj) return true;
                
    if ((obj == null|| (obj.GetType() != GetType())) return false;
                Person castObj 
    = (Person) obj;
                
    return (castObj != null&&
                       (_personid 
    == castObj.PersonId);
            }


            
    /// <summary>
            
    /// local implementation of GetHashCode based on unique value members
            
    /// </summary>

            public override int GetHashCode()
            
    {
                
    int hash = 57;
                hash 
    = 27*hash*_personid.GetHashCode();
                
    return hash;
            }


            
    #endregion
        }

    }
    /*
    /*作者:DDL
    /*联系:
    http://renrenqq.cnblogs.com/
    */


    using System;

    namespace DDLLY.TestNHibernate.TestAssociation.OneToOne
    {
        
    /// <summary>
        
    ///    
        
    /// </summary>

        [Serializable]
        
    public class Employee
        
    {
            
    Private Members Private Members

            
    private bool _isChanged;
            
    private bool _isDeleted;
            
    private int _personid;
            
    private string _job;
            
    private Person _person;

            
    #endregion


            
    Default ( Empty ) Class Constuctor Default ( Empty ) Class Constuctor

            
    /// <summary>
            
    /// default constructor
            
    /// </summary>

            public Employee()
            
    {
                _personid 
    = 0;
                _job 
    = null;
                _person 
    = null;
            }


            
    #endregion
     // End of Default ( Empty ) Class Constuctor

            
    Public Properties Public Properties

            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual int PersonId
            
    {
                
    get return _personid; }
                
    set
                
    {
                    _isChanged 
    |= (_personid != value);
                    _personid 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string Job
            
    {
                
    get return _job; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 64)
                            
    throw new ArgumentOutOfRangeException("Invalid value for Job", value, value.ToString());

                    _isChanged 
    |= (_job != value);
                    _job 
    = value;
                }

            }


            
    public Person Person
            
    {
                
    get return _person; }
                
    set { _person = value; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsChanged
            
    {
                
    get return _isChanged; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsDeleted
            
    {
                
    get return _isDeleted; }
            }


            
    #endregion

            
    Public Functions Public Functions

            
    /// <summary>
            
    /// mark the item as deleted
            
    /// </summary>

            public void MarkAsDeleted()
            
    {
                _isDeleted 
    = true;
                _isChanged 
    = true;
            }


            
    #endregion

            
    Equals And HashCode Overrides Equals And HashCode Overrides

            
    /// <summary>
            
    /// local implementation of Equals based on unique value members
            
    /// </summary>

            public override bool Equals(object obj)
            
    {
                
    if (this == obj) return true;
                
    if ((obj == null|| (obj.GetType() != GetType())) return false;
                Employee castObj 
    = (Employee) obj;
                
    return (castObj != null&&
                       (_personid 
    == castObj.PersonId);
            }


            
    /// <summary>
            
    /// local implementation of GetHashCode based on unique value members
            
    /// </summary>

            public override int GetHashCode()
            
    {
                
    int hash = 57;
                hash 
    = 27*hash*_personid.GetHashCode();
                
    return hash;
            }


            
    #endregion
        }

    }

    1.3 示例映射文件

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
        
    <class name="DDLLY.TestNHibernate.TestAssociation.OneToOne.Person,DDLLY.TestNHibernate.TestAssociation" table="T_Person">

            
    <id name="PersonId" column="PersonId" type="Int32" unsaved-value="0">
                
    <generator class="native"/>
            
    </id>
            
    <property column="Name" type="String" name="Name" length="64" />

        
    <one-to-one name="Employee" class="DDLLY.TestNHibernate.TestAssociation.OneToOne.Employee,DDLLY.TestNHibernate.TestAssociation" cascade="all"></one-to-one>
            
        
    </class>
    </hibernate-mapping>
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
        
    <class name="DDLLY.TestNHibernate.TestAssociation.OneToOne.Employee,DDLLY.TestNHibernate.TestAssociation" table="T_Employee">

            
    <id name="PersonId" column="PersonId" type="Int32" unsaved-value="0">
          
    <generator class="foreign">
            
    <param name="property">Person</param>
          
    </generator>
            
    </id>
            
    <property column="Job" type="String" name="Job" length="64" />

        
    <one-to-one name="Person" class="DDLLY.TestNHibernate.TestAssociation.OneToOne.Person,DDLLY.TestNHibernate.TestAssociation" constrained="true"></one-to-one>
            
        
    </class>
    </hibernate-mapping>

    1.4 说明

    constrained(约束): 表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。这个选项影响Save()和Delete()在级联执行时的先后顺序(也在schema export tool中被使用)。

    property-ref: (可选) 指定关联类的一个属性,这个属性将会和本外键相对应。如果没有指定,会使用对方关联类的主键。

    <generator class="foreign">:表示使用另外一个相关联的对象的标识符,来创建主健。T_Employee的PersonId来自T_Person的ParentId。

    Employee依赖于Person,所以通常在Person设置cascade。

    2.另一种one-to-one

    2.1数据库表结构

    其中T_Person1为主表,T_Employee1为子表。T_Employee1的PersonId设置唯一约束,参照T_Person1的PersonId。

    2.2示例映射类文件

    /*
    /*作者:DDL
    /*联系:
    http://renrenqq.cnblogs.com/
    */


    using System;

    namespace DDLLY.TestNHibernate.TestAssociation.OneToOne1
    {
        
    /// <summary>
        
    ///    
        
    /// </summary>

        [Serializable]
        
    public class Person
        
    {
            
    Private Members Private Members

            
    private bool _isChanged;
            
    private bool _isDeleted;
            
    private int _personid;
            
    private string _name;
            
    private Employee _employee;

            
    #endregion


            
    Default ( Empty ) Class Constuctor Default ( Empty ) Class Constuctor

            
    /// <summary>
            
    /// default constructor
            
    /// </summary>

            public Person()
            
    {
                _personid 
    = 0;
                _name 
    = null;
                _employee 
    = null;
            }


            
    #endregion
     // End of Default ( Empty ) Class Constuctor

            
    Public Properties Public Properties

            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual int PersonId
            
    {
                
    get return _personid; }
                
    set
                
    {
                    _isChanged 
    |= (_personid != value);
                    _personid 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string Name
            
    {
                
    get return _name; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 64)
                            
    throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());

                    _isChanged 
    |= (_name != value);
                    _name 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>

            public Employee Employee
            
    {
                
    get return _employee; }
                
    set { _employee = value; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsChanged
            
    {
                
    get return _isChanged; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsDeleted
            
    {
                
    get return _isDeleted; }
            }


            
    #endregion

            
    Public Functions Public Functions

            
    /// <summary>
            
    /// mark the item as deleted
            
    /// </summary>

            public void MarkAsDeleted()
            
    {
                _isDeleted 
    = true;
                _isChanged 
    = true;
            }


            
    #endregion

            
    Equals And HashCode Overrides Equals And HashCode Overrides

            
    /// <summary>
            
    /// local implementation of Equals based on unique value members
            
    /// </summary>

            public override bool Equals(object obj)
            
    {
                
    if (this == obj) return true;
                
    if ((obj == null|| (obj.GetType() != GetType())) return false;
                Person castObj 
    = (Person) obj;
                
    return (castObj != null&&
                       (_personid 
    == castObj.PersonId);
            }


            
    /// <summary>
            
    /// local implementation of GetHashCode based on unique value members
            
    /// </summary>

            public override int GetHashCode()
            
    {
                
    int hash = 57;
                hash 
    = 27*hash*_personid.GetHashCode();
                
    return hash;
            }


            
    #endregion
        }

    }
    /*
    /*作者:DDL
    /*联系:
    http://renrenqq.cnblogs.com/
    */


    using System;

    namespace DDLLY.TestNHibernate.TestAssociation.OneToOne1
    {
        
    /// <summary>
        
    ///    
        
    /// </summary>

        [Serializable]
        
    public class Employee
        
    {
            
    Private Members Private Members

            
    private bool _isChanged;
            
    private bool _isDeleted;
            
    private int _employeeId;
            
    private string _job;
            
    private Person _person;

            
    #endregion


            
    Default ( Empty ) Class Constuctor Default ( Empty ) Class Constuctor

            
    /// <summary>
            
    /// default constructor
            
    /// </summary>

            public Employee()
            
    {
                _employeeId 
    = 0;
                _job 
    = null;
                _person 
    = null;
            }


            
    #endregion
     // End of Default ( Empty ) Class Constuctor

            
    Public Properties Public Properties

            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual int EmployeeId
            
    {
                
    get return _employeeId; }
                
    set
                
    {
                    _isChanged 
    |= (_employeeId != value);
                    _employeeId 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string Job
            
    {
                
    get return _job; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 64)
                            
    throw new ArgumentOutOfRangeException("Invalid value for Job", value, value.ToString());

                    _isChanged 
    |= (_job != value);
                    _job 
    = value;
                }

            }


            
    public Person Person
            
    {
                
    get return _person; }
                
    set { _person = value; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsChanged
            
    {
                
    get return _isChanged; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsDeleted
            
    {
                
    get return _isDeleted; }
            }


            
    #endregion

            
    Public Functions Public Functions

            
    /// <summary>
            
    /// mark the item as deleted
            
    /// </summary>

            public void MarkAsDeleted()
            
    {
                _isDeleted 
    = true;
                _isChanged 
    = true;
            }


            
    #endregion

            
    Equals And HashCode Overrides Equals And HashCode Overrides

            
    /// <summary>
            
    /// local implementation of Equals based on unique value members
            
    /// </summary>

            public override bool Equals(object obj)
            
    {
                
    if (this == obj) return true;
                
    if ((obj == null|| (obj.GetType() != GetType())) return false;
                Employee castObj 
    = (Employee) obj;
                
    return (castObj != null&&
                       (_employeeId 
    == castObj.EmployeeId);
            }


            
    /// <summary>
            
    /// local implementation of GetHashCode based on unique value members
            
    /// </summary>

            public override int GetHashCode()
            
    {
                
    int hash = 57;
                hash 
    = 27*hash*_employeeId.GetHashCode();
                
    return hash;
            }


            
    #endregion
        }

    }


    2.3示例映射文件

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
        
    <class name="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Person,DDLLY.TestNHibernate.TestAssociation" table="T_Person1">

            
    <id name="PersonId" column="PersonId" type="Int32" unsaved-value="0">
                
    <generator class="native"/>
            
    </id>
            
    <property column="Name" type="String" name="Name" length="64" />

        
    <one-to-one name="Employee" class="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Employee,DDLLY.TestNHibernate.TestAssociation" cascade="all"></one-to-one>
            
        
    </class>
    </hibernate-mapping>


    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
        
    <class name="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Employee,DDLLY.TestNHibernate.TestAssociation" table="T_Employee1">

            
    <id name="EmployeeId" column="EmployeeId" type="Int32" unsaved-value="0">
          
    <generator class="native"/>
        
    </id>
        
    <property column="Job" type="String" name="Job" length="64" />

        
    <many-to-one name="Person" class="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Person,DDLLY.TestNHibernate.TestAssociation" column="PersonId"  unique="true"></many-to-one>
            
        
    </class>
    </hibernate-mapping>

    2.4说明

    这种one-to-one实际上是一种特殊的one-to-many,如果T_Employee1的PersonId不设置唯一约束,则可成为 one-to-many。所以在T_Employee端设置many-to-one而不是one-to-one,记住要加上unique="true"表 示唯一约束。

    3.one-to-many

    3.1 数据库表结构

    T_Parent为主表,T_Child的ParentId参照T_Parent的ParentId。

    注意:对于单向的one-to-many映射,cascade过程中会用到把T_Child表的ParentId设置为Null,所以ParentId应设为允许NULL;

    而双向one-to-many映射,建议把T_Child的ParentI设置为不允许NULL

    3.2 示例映射类文件(单向)

    /*
    /*作者:DDL
    /*联系:
    http://renrenqq.cnblogs.com/
    */


    using System;
    using System.Collections;

    namespace DDLLY.TestNHibernate.TestAssociation.OneToMany1
    {
        
    /// <summary>
        
    ///    
        
    /// </summary>

        [Serializable]
        
    public class Parent
        
    {
            
    Private Members Private Members

            
    private bool _isChanged;
            
    private bool _isDeleted;
            
    private int _parentid;
            
    private string _name;
            
    private IList _children;

            
    #endregion


            
    Default ( Empty ) Class Constuctor Default ( Empty ) Class Constuctor

            
    /// <summary>
            
    /// default constructor
            
    /// </summary>

            public Parent()
            
    {
                _parentid 
    = 0;
                _name 
    = null;
                _children 
    = new ArrayList();
            }


            
    #endregion
     // End of Default ( Empty ) Class Constuctor

            
    Public Properties Public Properties

            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual int ParentId
            
    {
                
    get return _parentid; }
                
    set
                
    {
                    _isChanged 
    |= (_parentid != value);
                    _parentid 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string Name
            
    {
                
    get return _name; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 64)
                            
    throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());

                    _isChanged 
    |= (_name != value);
                    _name 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual IList Children
            
    {
                
    get return _children; }
                
    set
                
    {
                    _isChanged 
    |= (_children != value);
                    _children 
    = value;
                }

            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsChanged
            
    {
                
    get return _isChanged; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsDeleted
            
    {
                
    get return _isDeleted; }
            }


            
    #endregion

            
    Public Functions Public Functions

            
    /// <summary>
            
    /// mark the item as deleted
            
    /// </summary>

            public void MarkAsDeleted()
            
    {
                _isDeleted 
    = true;
                _isChanged 
    = true;
            }


            
    #endregion

            
    Equals And HashCode Overrides Equals And HashCode Overrides

            
    /// <summary>
            
    /// local implementation of Equals based on unique value members
            
    /// </summary>

            public override bool Equals(object obj)
            
    {
                
    if (this == obj) return true;
                
    if ((obj == null|| (obj.GetType() != GetType())) return false;
                Parent castObj 
    = (Parent) obj;
                
    return (castObj != null&&
                       (_parentid 
    == castObj.ParentId);
            }


            
    /// <summary>
            
    /// local implementation of GetHashCode based on unique value members
            
    /// </summary>

            public override int GetHashCode()
            
    {
                
    int hash = 57;
                hash 
    = 27*hash*_parentid.GetHashCode();
                
    return hash;
            }


            
    #endregion
        }

    }
    /*
    /*作者:DDL
    /*联系:
    http://renrenqq.cnblogs.com/
    */


    using System;

    namespace DDLLY.TestNHibernate.TestAssociation.OneToMany1
    {
        
    /// <summary>
        
    ///    
        
    /// </summary>

        [Serializable]
        
    public class Child
        
    {
            
    Private Members Private Members

            
    private bool _isChanged;
            
    private bool _isDeleted;
            
    private int _childid;
            
    private string _name;
            
    private int _parentid;

            
    #endregion


            
    Default ( Empty ) Class Constuctor Default ( Empty ) Class Constuctor

            
    /// <summary>
            
    /// default constructor
            
    /// </summary>

            public Child()
            
    {
                _childid 
    = 0;
                _name 
    = null;
                _parentid 
    = 0;
            }


            
    #endregion
     // End of Default ( Empty ) Class Constuctor

            
    Public Properties Public Properties

            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual int ChildId
            
    {
                
    get return _childid; }
                
    set
                
    {
                    _isChanged 
    |= (_childid != value);
                    _childid 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string Name
            
    {
                
    get return _name; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 64)
                            
    throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());

                    _isChanged 
    |= (_name != value);
                    _name 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual int ParentId
            
    {
                
    get return _parentid; }
                
    set
                
    {
                    _isChanged 
    |= (_parentid != value);
                    _parentid 
    = value;
                }

            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsChanged
            
    {
                
    get return _isChanged; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsDeleted
            
    {
                
    get return _isDeleted; }
            }


            
    #endregion 

            
    Public Functions Public Functions

            
    /// <summary>
            
    /// mark the item as deleted
            
    /// </summary>

            public void MarkAsDeleted()
            
    {
                _isDeleted 
    = true;
                _isChanged 
    = true;
            }


            
    #endregion

            
    Equals And HashCode Overrides Equals And HashCode Overrides

            
    /// <summary>
            
    /// local implementation of Equals based on unique value members
            
    /// </summary>

            public override bool Equals(object obj)
            
    {
                
    if (this == obj) return true;
                
    if ((obj == null|| (obj.GetType() != GetType())) return false;
                Child castObj 
    = (Child) obj;
                
    return (castObj != null&&
                       (_childid 
    == castObj.ChildId);
            }


            
    /// <summary>
            
    /// local implementation of GetHashCode based on unique value members
            
    /// </summary>

            public override int GetHashCode()
            
    {
                
    int hash = 57;
                hash 
    = 27*hash*_childid.GetHashCode();
                
    return hash;
            }


            
    #endregion
        }

    }

    3.3 示例映射文件(单向)

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
        
    <class name="DDLLY.TestNHibernate.TestAssociation.OneToMany1.Parent,DDLLY.TestNHibernate.TestAssociation" table="T_Parent">

            
    <id name="ParentId" column="ParentId" type="Int32" unsaved-value="0">
                
    <generator class="native"/>
            
    </id>
            
    <property column="Name" type="String" name="Name" length="64" />
        
        
    <bag name="Children" cascade="all"  lazy="true">
          
    <key column="ParentId"/>
          
    <one-to-many class="DDLLY.TestNHibernate.TestAssociation.OneToMany1.Child,DDLLY.TestNHibernate.TestAssociation"/>
        
    </bag>        
        
        
    </class>
    </hibernate-mapping>
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
        
    <class name="DDLLY.TestNHibernate.TestAssociation.OneToMany1.Child,DDLLY.TestNHibernate.TestAssociation" table="T_Child">

            
    <id name="ChildId" column="ChildId" type="Int32" unsaved-value="0">
                
    <generator class="native"/>
            
    </id>
            
    <property column="Name" type="String" name="Name" length="64" />
        
    <property column="ParentId" type="Int32" name="ParentId"/>
            
        
    </class>
    </hibernate-mapping>

    3.4 示例映射类文件(双向)

    /*
    /*作者:DDL
    /*联系:
    http://renrenqq.cnblogs.com/
    */


    using System;
    using System.Collections;

    namespace DDLLY.TestNHibernate.TestAssociation.OneToMany
    {
        
    /// <summary>
        
    ///    
        
    /// </summary>

        [Serializable]
        
    public class Parent
        
    {
            
    Private Members Private Members

            
    private bool _isChanged;
            
    private bool _isDeleted;
            
    private int _parentid;
            
    private string _name;
            
    private IList _children;

            
    #endregion


            
    Default ( Empty ) Class Constuctor Default ( Empty ) Class Constuctor

            
    /// <summary>
            
    /// default constructor
            
    /// </summary>

            public Parent()
            
    {
                _parentid 
    = 0;
                _name 
    = null;
                _children 
    = new ArrayList();
            }


            
    #endregion
     // End of Default ( Empty ) Class Constuctor

            
    Public Properties Public Properties

            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual int ParentId
            
    {
                
    get return _parentid; }
                
    set
                
    {
                    _isChanged 
    |= (_parentid != value);
                    _parentid 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string Name
            
    {
                
    get return _name; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 64)
                            
    throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());

                    _isChanged 
    |= (_name != value);
                    _name 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual IList Children
            
    {
                
    get return _children; }
                
    set
                
    {
                    _isChanged 
    |= (_children != value);
                    _children 
    = value;
                }

            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsChanged
            
    {
                
    get return _isChanged; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsDeleted
            
    {
                
    get return _isDeleted; }
            }


            
    #endregion

            
    Public Functions Public Functions

            
    /// <summary>
            
    /// mark the item as deleted
            
    /// </summary>

            public void MarkAsDeleted()
            
    {
                _isDeleted 
    = true;
                _isChanged 
    = true;
            }


            
    #endregion

            
    Equals And HashCode Overrides Equals And HashCode Overrides

            
    /// <summary>
            
    /// local implementation of Equals based on unique value members
            
    /// </summary>

            public override bool Equals(object obj)
            
    {
                
    if (this == obj) return true;
                
    if ((obj == null|| (obj.GetType() != GetType())) return false;
                Parent castObj 
    = (Parent) obj;
                
    return (castObj != null&&
                       (_parentid 
    == castObj.ParentId);
            }


            
    /// <summary>
            
    /// local implementation of GetHashCode based on unique value members
            
    /// </summary>

            public override int GetHashCode()
            
    {
                
    int hash = 57;
                hash 
    = 27*hash*_parentid.GetHashCode();
                
    return hash;
            }


            
    #endregion
        }

    }
    /*
    /*作者:DDL
    /*联系:
    http://renrenqq.cnblogs.com/
    */


    using System;

    namespace DDLLY.TestNHibernate.TestAssociation.OneToMany
    {
        
    /// <summary>
        
    ///    
        
    /// </summary>

        [Serializable]
        
    public class Child
        
    {
            
    Private Members Private Members

            
    private bool _isChanged;
            
    private bool _isDeleted;
            
    private int _childid;
            
    private string _name;
            
    private Parent _parent;

            
    #endregion


            
    Default ( Empty ) Class Constuctor Default ( Empty ) Class Constuctor

            
    /// <summary>
            
    /// default constructor
            
    /// </summary>

            public Child()
            
    {
                _childid 
    = 0;
                _name 
    = null;
                _parent 
    = null;
            }


            
    #endregion
     // End of Default ( Empty ) Class Constuctor

            
    Public Properties Public Properties

            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual int ChildId
            
    {
                
    get return _childid; }
                
    set
                
    {
                    _isChanged 
    |= (_childid != value);
                    _childid 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string Name
            
    {
                
    get return _name; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 64)
                            
    throw new ArgumentOutOfRangeException("Invalid value for Name", value, value.ToString());

                    _isChanged 
    |= (_name != value);
                    _name 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual Parent Parent
            
    {
                
    get return _parent; }
                
    set
                
    {
                    _isChanged 
    |= (_parent != value);
                    _parent 
    = value;
                }

            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsChanged
            
    {
                
    get return _isChanged; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsDeleted
            
    {
                
    get return _isDeleted; }
            }


            
    #endregion 

            
    Public Functions Public Functions

            
    /// <summary>
            
    /// mark the item as deleted
            
    /// </summary>

            public void MarkAsDeleted()
            
    {
                _isDeleted 
    = true;
                _isChanged 
    = true;
            }


            
    #endregion

            
    Equals And HashCode Overrides Equals And HashCode Overrides

            
    /// <summary>
            
    /// local implementation of Equals based on unique value members
            
    /// </summary>

            public override bool Equals(object obj)
            
    {
                
    if (this == obj) return true;
                
    if ((obj == null|| (obj.GetType() != GetType())) return false;
                Child castObj 
    = (Child) obj;
                
    return (castObj != null&&
                       (_childid 
    == castObj.ChildId);
            }


            
    /// <summary>
            
    /// local implementation of GetHashCode based on unique value members
            
    /// </summary>

            public override int GetHashCode()
            
    {
                
    int hash = 57;
                hash 
    = 27*hash*_childid.GetHashCode();
                
    return hash;
            }


            
    #endregion
        }

    }

    3.5 示例映射类文件(双向)

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
        
    <class name="DDLLY.TestNHibernate.TestAssociation.OneToMany.Parent,DDLLY.TestNHibernate.TestAssociation" table="T_Parent">

            
    <id name="ParentId" column="ParentId" type="Int32" unsaved-value="0">
                
    <generator class="native"/>
            
    </id>
            
    <property column="Name" type="String" name="Name" length="64" />
        
        
    <bag name="Children" cascade="all" inverse="true" lazy="true">
          
    <key column="ParentId"/>
          
    <one-to-many class="DDLLY.TestNHibernate.TestAssociation.OneToMany.Child,DDLLY.TestNHibernate.TestAssociation"/>
        
    </bag>        
        
        
    </class>
    </hibernate-mapping>
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
        
    <class name="DDLLY.TestNHibernate.TestAssociation.OneToMany.Child,DDLLY.TestNHibernate.TestAssociation" table="T_Child">

            
    <id name="ChildId" column="ChildId" type="Int32" unsaved-value="0">
                
    <generator class="native"/>
            
    </id>
            
    <property column="Name" type="String" name="Name" length="64" />
        
            
    <many-to-one name="Parent" column="ParentId" class="DDLLY.TestNHibernate.TestAssociation.OneToMany.Parent,DDLLY.TestNHibernate.TestAssociation" />
            
        
    </class>
    </hibernate-mapping>

    3.6 说明

    在NHibernate配置文件中使用<set>, <list>, <map>, <bag>, <array> 和 <primitive-array>等元素来定义集合。<bag>是典型的一个,代码中我们用IList和它对应。我们以后会详 细讲集合这个话题。

    lazy表示允许延迟加载。表示在需要使用时才加载需要的数据。例如使用lazy时我们Load一个Parent他的Children为空,只有我 们访问它的某一个Child时数据才会被加载;而不设置lazy我们Load一个Parent时其Children将同时加载。注意:使用lazy加载必 须保证对应ISession的打开,否则懒加载会失败。

    one-to-many可以设置单向和双向映射,设置单向时Child一段不设置many-to-one,而设置了ParentId的属性。

    双向映射需要设置inverse而单向不需要。

    单项映射在cascade时会对把T_Child的ParentId使用Update为Null的操作。

    建议尽量使用双向映射。

    4.many-to-many

    4.1 数据库表结构

    4.2 示例映射类文件

    /*
    /*作者:DDL
    /*联系:
    http://renrenqq.cnblogs.com/
    */


    using System;
    using System.Collections;

    namespace DDLLY.TestNHibernate.TestAssociation.ManyToMany
    {
        
    /// <summary>
        
    ///    
        
    /// </summary>

        [Serializable]
        
    public class User
        
    {
            
    Private Members Private Members

            
    private bool _isChanged;
            
    private bool _isDeleted;
            
    private int _userid;
            
    private string _username;
            
    private string _password;
            
    private string _email;
            
    private IList _roles;

            
    #endregion


            
    Default ( Empty ) Class Constuctor Default ( Empty ) Class Constuctor

            
    /// <summary>
            
    /// default constructor
            
    /// </summary>

            public User()
            
    {
                _userid 
    = 0;
                _username 
    = null;
                _password 
    = null;
                _email 
    = null;
                _roles 
    = new ArrayList();
            }


            
    #endregion
     // End of Default ( Empty ) Class Constuctor

            
    Public Properties Public Properties

            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual int UserId
            
    {
                
    get return _userid; }
                
    set
                
    {
                    _isChanged 
    |= (_userid != value);
                    _userid 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string UserName
            
    {
                
    get return _username; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 64)
                            
    throw new ArgumentOutOfRangeException("Invalid value for UserName", value, value.ToString());

                    _isChanged 
    |= (_username != value);
                    _username 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string Password
            
    {
                
    get return _password; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 32)
                            
    throw new ArgumentOutOfRangeException("Invalid value for Password", value, value.ToString());

                    _isChanged 
    |= (_password != value);
                    _password 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string Email
            
    {
                
    get return _email; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 64)
                            
    throw new ArgumentOutOfRangeException("Invalid value for Email", value, value.ToString());

                    _isChanged 
    |= (_email != value);
                    _email 
    = value;
                }

            }


            
    public IList Roles
            
    {
                
    get return _roles; }
                
    set { _roles = value; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsChanged
            
    {
                
    get return _isChanged; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsDeleted
            
    {
                
    get return _isDeleted; }
            }


            
    #endregion

            
    Public Functions Public Functions

            
    /// <summary>
            
    /// mark the item as deleted
            
    /// </summary>

            public void MarkAsDeleted()
            
    {
                _isDeleted 
    = true;
                _isChanged 
    = true;
            }


            
    #endregion

            
    Equals And HashCode Overrides Equals And HashCode Overrides

            
    /// <summary>
            
    /// local implementation of Equals based on unique value members
            
    /// </summary>

            public override bool Equals(object obj)
            
    {
                
    if (this == obj) return true;
                
    if ((obj == null|| (obj.GetType() != GetType())) return false;
                User castObj 
    = (User) obj;
                
    return (castObj != null&&
                       (_userid 
    == castObj.UserId);
            }


            
    /// <summary>
            
    /// local implementation of GetHashCode based on unique value members
            
    /// </summary>

            public override int GetHashCode()
            
    {
                
    int hash = 57;
                hash 
    = 27*hash*_userid.GetHashCode();
                
    return hash;
            }


            
    #endregion
        }

    }
    /*
    /*作者:DDL
    /*联系:
    http://renrenqq.cnblogs.com/
    */


    using System;
    using System.Collections;

    namespace DDLLY.TestNHibernate.TestAssociation.ManyToMany
    {
        
    /// <summary>
        
    ///    
        
    /// </summary>

        [Serializable]
        
    public class Role
        
    {
            
    Private Members Private Members

            
    private bool _isChanged;
            
    private bool _isDeleted;
            
    private int _roleid;
            
    private string _rolename;
            
    private IList _users;

            
    #endregion


            
    Default ( Empty ) Class Constuctor Default ( Empty ) Class Constuctor

            
    /// <summary>
            
    /// default constructor
            
    /// </summary>

            public Role()
            
    {
                _roleid 
    = 0;
                _rolename 
    = null;
                _users 
    = new ArrayList();
            }


            
    #endregion
     // End of Default ( Empty ) Class Constuctor

            
    Public Properties Public Properties

            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual int RoleId
            
    {
                
    get return _roleid; }
                
    set
                
    {
                    _isChanged 
    |= (_roleid != value);
                    _roleid 
    = value;
                }

            }


            
    /// <summary>
            
    /// 
            
    /// </summary>        

            public virtual string RoleName
            
    {
                
    get return _rolename; }
                
    set
                
    {
                    
    if (value != null)
                        
    if (value.Length > 64)
                            
    throw new ArgumentOutOfRangeException("Invalid value for RoleName", value, value.ToString());

                    _isChanged 
    |= (_rolename != value);
                    _rolename 
    = value;
                }

            }


            
    public IList Users
            
    {
                
    get return _users; }
                
    set { _users = value; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsChanged
            
    {
                
    get return _isChanged; }
            }


            
    /// <summary>
            
    /// Returns whether or not the object has changed it's values.
            
    /// </summary>

            public bool IsDeleted
            
    {
                
    get return _isDeleted; }
            }


            
    #endregion

            
    Public Functions Public Functions

            
    /// <summary>
            
    /// mark the item as deleted
            
    /// </summary>

            public void MarkAsDeleted()
            
    {
                _isDeleted 
    = true;
                _isChanged 
    = true;
            }


            
    #endregion

            
    Equals And HashCode Overrides Equals And HashCode Overrides

            
    /// <summary>
            
    /// local implementation of Equals based on unique value members
            
    /// </summary>

            public override bool Equals(object obj)
            
    {
                
    if (this == obj) return true;
                
    if ((obj == null|| (obj.GetType() != GetType())) return false;
                Role castObj 
    = (Role) obj;
                
    return (castObj != null&&
                       (_roleid 
    == castObj.RoleId);
            }


            
    /// <summary>
            
    /// local implementation of GetHashCode based on unique value members
            
    /// </summary>

            public override int GetHashCode()
            
    {
                
    int hash = 57;
                hash 
    = 27*hash*_roleid.GetHashCode();
                
    return hash;
            }


            
    #endregion
        }

    }

    4.3 示例映射文件

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
        
    <class name="DDLLY.TestNHibernate.TestAssociation.ManyToMany.User,DDLLY.TestNHibernate.TestAssociation" table="T_User">

            
    <id name="UserId" column="UserId" type="Int32" unsaved-value="0">
                
    <generator class="native"/>
            
    </id>
            
    <property column="UserName" type="String" name="UserName" not-null="true" length="64" />
            
    <property column="Password" type="String" name="Password" not-null="true" length="32" />
            
    <property column="Email" type="String" name="Email" length="64" />

        
    <bag name="Roles" table="T_User_Role" lazy="true">
          
    <key column="UserId"/>
          
    <many-to-many class="DDLLY.TestNHibernate.TestAssociation.ManyToMany.Role,DDLLY.TestNHibernate.TestAssociation" column="RoleId"/>
        
    </bag>
            
        
    </class>
    </hibernate-mapping>
    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
        
    <class name="DDLLY.TestNHibernate.TestAssociation.ManyToMany.Role,DDLLY.TestNHibernate.TestAssociation" table="T_Role">

            
    <id name="RoleId" column="RoleId" type="Int32" unsaved-value="0">
                
    <generator class="native"/>
            
    </id>
            
    <property column="RoleName" type="String" name="RoleName" not-null="true" length="64" />

        
    <bag name="Users" table="T_User_Role" lazy="true" inverse="true">
          
    <key column="RoleId"/>
          
    <many-to-many class="DDLLY.TestNHibernate.TestAssociation.ManyToMany.User,DDLLY.TestNHibernate.TestAssociation" column="UserId"/>
        
    </bag>


      
    </class>
    </hibernate-mapping>

    4.4 说明

    many-to-many性能不佳,数据量大时应尽可能避免使用。并尽可能使用lazy="true"。

    在数据量少的一端设置inverse="true",让数据量多的一段维护cascade。

    二、cascade分析

    1.总述

    cascade:(默认为none)级联。指明哪些操作会从对象级联到关联的对象。

    orphans:孤儿,没有夫对象的子对象。对于代码Child.Parent==null,对于数据库T_Child表中ParentId为Null的数据。

    delete orphans表示cascade时删除孤儿。

    一般系统中是不允许孤儿存在的,我们可以通过数据库的约束来限制孤儿,例如T_Child的ParentId设为Not NULL。

    如果确实存在孤儿请考虑适合的cascade策略。

    cascade类型 对应操作

    all

    Save / Delete / Update

    all-delete-orphan

    Save / Delete / Update + delete orphans

    delete-orphan

    Delete + delete orphans

    none

    No Cascades

    delete

    Delete

    save-update

    Save / Update

     2.one-to-one

    a.初始化数据

    PersonId Name Job
    1 DDL 编程
    2 LLY NULL

    b.测试方法

    TestAddPersonWithAddEmployee

    Person person = new Person();
    person.Name 
    = "newPerson";
    Employee employee 
    = new Employee();
    employee.Job 
    = "newJob";
    person.Employee 
    = employee;
    employee.Person 
    = person;

    session.Save(person);

    TestUpdatePersonWithAddEmployee

    Person person = session.Load(typeof (Person), 2as Person;
    person.Employee 
    = new Employee();
    person.Employee.Person 
    = person;
    person.Employee.Job 
    = "LLYJob";

    session.Update(person);

    TestUpdatePersonWithUpdateEmployee

    Person person = session.Load(typeof (Person), 1as Person;
    person.Employee.Job 
    = "DDL'New Job";

    session.Update(person);

    TestDeletePersonWithDeleteEmployee

    Person person = session.Load(typeof (Person), 1as Person;

    session.Delete(person);

    c.测试结果

    测试方法

    save-update

    delete

    delete-orphan

    all

    all-delete-orphan

    none

    TestAddPersonWithAddEmployee

    Y

    N

    N

    Y

    Y

    N

    TestUpdatePersonWithAddEmployee

    Y

    N

    N

    Y

    Y

    N

    TestUpdatePersonWithUpdateEmployee

    Y

    Y

    Y

    Y

    Y

    Y

    TestDeletePersonWithDeleteEmployee

    N

    Y

    Y

    Y

    Y

    N

     2.另一种one-to-one

    a.初始化数据

    PersonId Name EmployeeId Job
    1 DDL 1 编程
    2 LLY NULL NULL

     b.测试方法

    TestAddPersonWithAddEmployee

    不支持

    TestUpdatePersonWithAddEmployee

    Person person = session.Load(typeof (Person), 2as Person;
    person.Employee 
    = new Employee();
    person.Employee.Person 
    = person;
    person.Employee.Job 
    = "LLYJob";

    session.Update(person);
    session.Flush();

    TestUpdatePersonWithUpdateEmployee

    Person person = session.Load(typeof (Person), 1as Person;
    person.Employee.Job 
    = "DDL'New Job";

    session.Update(person);
    session.Flush();

     TestDeletePersonWithDeleteEmployee

    Person person = session.Load(typeof (Person), 1as Person;

    session.Delete(person);
    session.Flush();

    c.测试结果

    测试方法

    save-update

    delete

    delete-orphan

    all

    all-delete-orphan

    none

    TestAddPersonWithAddEmployee

    不支持

    不支持

    不支持

    不支持

    不支持

    不支持

    TestUpdatePersonWithAddEmployee

    Y

    N

    N

    Y

    Y

    N

    TestUpdatePersonWithUpdateEmployee

    Y

    Y

    Y

    Y

    Y

    Y

    TestDeletePersonWithDeleteEmployee

    N

    Y

    Y

    Y

    Y

    N

    3.one-to-many(双向)

    a.初始化数据

    ParentId ParentName ChildId ChildName
    1 Parent1 1 Child1
    2 Parent2 NULL NULL

    b.测试方法

    TestAddParentWithAddChild

    Parent parent = new Parent();
    parent.Name 
    = "NewParent";

    Child child 
    = new Child();
    child.Name 
    = "NewChild";
    child.Parent 
    = parent;

    parent.Children.Add(child);

    session.Save(parent);
    session.Flush();

    TestUpdateParentWithAddChild

    Parent parent = session.Load(typeof (Parent), 2as Parent;

    Child child 
    = new Child();
    child.Name 
    = "NewChild";
    child.Parent 
    = parent;

    parent.Children.Add(child);

    session.Update(parent);

    session.Flush();

    TestUpdateParentWithUpdateChild

    Parent parent = session.Load(typeof (Parent), 1as Parent;

    Child child 
    = (Child) parent.Children[0];

    child.Name 
    = "UpdateName";

    session.Update(parent);

    session.Flush();

    TestDeleteParentWithChild

    Parent parent = session.Load(typeof (Parent), 1as Parent;

    session.Delete(parent);
    session.Flush();

     c.测试结果

    测试方法

    save-update

    delete

    delete-orphan

    all

    all-delete-orphan

    none

    TestAddParentWithAddChild Y N N Y Y N
    TestUpdateParentWithAddChild Y N N Y Y N
    TestUpdateParentWithUpdateChild Y Y Y Y Y Y
    TestDeleteParentWithChild N Y Y Y Y N

    4.one-to-many(单向)

    a.初始化数据

    同上

    b.测试方法

    TestAddParentWithAddChild

    不支持

    TestUpdateParentWithAddChild

    Parent parent = session.Load(typeof (Parent), 2as Parent;

    Child child 
    = new Child();
    child.Name 
    = "NewChild";
    child.ParentId 
    = parent.ParentId;

    parent.Children.Add(child);

    session.Update(parent);

    session.Flush();

    TestUpdateParentWithUpdateChild

    Parent parent = session.Load(typeof (Parent), 1as Parent;

    Child child 
    = (Child) parent.Children[0];

    child.Name 
    = "UpdateName";

    session.Update(parent);

    session.Flush();

    TestDeleteParentWithChild

    Parent parent = session.Load(typeof (Parent), 1as Parent;

    session.Delete(parent);

    session.Flush();

     c.测试结果

    测试方法

    save-update

    delete

    delete-orphan

    all

    all-delete-orphan

    none

    TestAddParentWithAddChild 不支持 不支持 不支持 不支持 不支持 不支持
    TestUpdateParentWithAddChild Y N N Y Y N
    TestUpdateParentWithUpdateChild Y Y Y Y Y Y
    TestDeleteParentWithChild Parent被删除,Child成为孤儿 Y Y Y Y Parent被删除,Child成为孤儿

    5.many-to-many
    many-to-many和别的关联映射有所不同。例子中:Role和User没有直接的依赖关系,而是通过一张中间表完成。在删除User时一般不会要求删除Role,而是删除之间的关系(即从中间表删除数据)。

    a.初始化数据

    UserId UserName Password Email RoleId RoleName
    1 DDL 1 NULL 1 角色1
    1 DDL 1 NULL 2 角色2
    2 LLY 2 NULL 1 角色1
    3 陌生人 3 NULL NULL NULL
    NULL NULL NULL NULL 3 角色3

    b.测试方法

    TestAddRoleToUser

    User user = session.Load(typeof (User), 1as User;
    Role role 
    = session.Load(typeof (Role), 3as Role;

    user.Roles.Add(role);
    role.Users.Add(user);

    session.Update(user);
    session.Flush();

     TestRemoveRoleFromUser

    User user = session.Load(typeof (User), 1as User;
    Role role 
    = session.Load(typeof (Role), 2as Role;

    user.Roles.Remove(role);
    role.Users.Remove(user);

    session.Update(user);
    session.Flush();

     

     TestUpdateUserWithRole

    User user = session.Load(typeof(User), 2as User;
    ((Role) user.Roles[
    0]).RoleName = "UpdateRole";

    session.Update(user);
    session.Flush();

    TestDeleteUserWithSetRole

    User user = session.Load(typeof (User), 1as User;
    session.Delete(user);
    session.Flush();

    c.测试结果

    测试方法

    save-update

    delete

    delete-orphan

    all

    all-delete-orphan

    none

    TestAddRoleToUser Y Y Y Y Y Y
    TestRemoveRoleFromUser Y Y Y Y Y Y
    TestUpdateUserWithRole Y Y Y Y Y Y
    TestDeleteUserWithSetRole N Uer被删除,但和其有关的Role也被删除 Uer被删除,但和其有关的Role也被删除 Uer被删除,但和其有关的Role也被删除 Uer被删除,但和其有关的Role也被删除 N

     三、结论

    关联是NHibernate里面功能很强的一块,但也使很容易滥用而造成引起性能或其他问题的地方。所以请慎重的使用。

    在使用之前,请考虑好以下问题:

    1.关系分析,一对多,多对多,还是一对一。

    2.确定依赖关系,例如:Child依赖于Parent。

    3.是否允许存在孤儿,例如:存在Child没有Parent(即在数据库中ParentId为Null的Child)。

    4.在对等的关系中是否有主动端。例如:需要给Parent设置Child还是给Child找Parent,或者两边都可以操作。

    5.关联两端可能出现的数据量以及在页面显示时是否分页。如果数据量大或者页面上需要分页显示,建议不要采用关联映射。如果数据量大,性能会不好,如果需要分页,关联所有数据似乎没有什么意思。

    6.页面上可能的对象操作方法。例如:先读取一个Parent,然后添加Child,然后保存。

    请根据你的情况设置关联映射,而对于cascade标准的设置可以满足绝大多数的需要,如一有特殊情况,请按照上面的分析选择合适的。

    下载代码

  • 相关阅读:
    centos x86_64--------------------------------系统调用
    通过tracing技术来教授操作系统
    Cobra —— 可视化Python虚拟机 and 图解python
    ArcGIS Engine中空间参照(地理坐标)相关方法总结
    ArcGIS Engine检索要素集、要素类和要素
    C#打开SDE数据库的几种方式总结
    ArcSDE:C#创建SDE要素数据集
    ORA-01653 无法在表空间扩展的解决办法 -- 增加表空间大小或给表空间增加数据文件
    3.第一个Node.js程序:Hello World!
    2.使用的版本
  • 原文地址:https://www.cnblogs.com/goody9807/p/1640917.html
Copyright © 2020-2023  润新知