Compatibilidad con colecciones de componentes en Entity Developer

Este artículo explica y proporciona un ejemplo práctico de cómo se implementa la compatibilidad con las colecciones de componentes en Entity Developer para NHibernate. Puede echar un vistazo más de cerca a este tipo de pantalla en la documentación de NHibernate aquí.
Este artículo proporciona ejemplos de visualización para las siguientes asociaciones:

  • Visualización clásica de colecciones de componentes;
  • Un caso especial de mostrar colecciones de componentes para combinar "muchos a muchos".
Índice

    Visualización clásica de colecciones de componentes:

    El mapeo clásico de colecciones de componentes es muy parecido al mapeo de conexiones de uno a muchos entre dos objetos modelo. La principal diferencia es que el modelo no tiene una entidad que coincida con la tabla de piezas, sino que el modelo contiene un tipo complejo que consta de un conjunto de propiedades similares a parte de un conjunto de campos de tabla de piezas. Mientras que la relación se construye entre la entidad correspondiente a la tabla principal y el tipo complejo correspondiente a la parte del conjunto de campos de la tabla parte. La esencia principal contiene la propiedad de navegación, que es una referencia a una colección de partes de tipos complejos.

    La base de datos que asigna uno a varios está diseñada como una tabla con una clave principal para un lado de visualización y una tabla que contiene un campo que hace referencia a la clave principal de la tabla maestra en el otro lado.

    Ejemplo:

    La base de datos contiene las tablas Dept y Emp, que tienen una restricción de clave externa entre ellas.
    El campo DEPTNO en la tabla Emp obtiene el valor del ID del registro asociado en la tabla Dept.

    diagrama de base de datos

    Realice la siguiente secuencia de operaciones:

    • crear un modelo NHibernate;
    • agregar tablas Dept y Emp al modelo;
    • seleccione parte de las propiedades de la entidad Emp (por ejemplo, las propiedades ENAME, JOB, MGR) y, arrastrándolas, selecciónelas en un tipo complejo separado, asígnele el nombre PartialEmpType y luego elimine el objeto Emp;
    • después de eso, agregamos un enlace entre la esencia principal de Dept y el tipo de parte compleja PartialEmpType y lo configuramos como se muestra en la siguiente captura de pantalla:

    Redactor de la Asociación

    У Redactor de la Asociación cuadro de diálogo únete a la mesa el campo de entrada especifica el nombre de la tabla de partes, y en Esquema el nombre del esquema en el que existe se ingresa en el campo. En el cuadro de diálogo, debe especificar el nombre de la columna de clave externa de la tabla de particiones que hace referencia a la clave principal de la tabla maestra.
    Este cuadro de diálogo también le permite definir una asignación privada para detalles de propiedades de tipo complejo con campos de detalles de campo si esta asignación de asociación es diferente de la asignación general de propiedades de tipo complejo.

    El valor predeterminado para este tipo de asociación es para las propiedades de navegación del extremo 1 Crear propiedad relacionada la casilla de verificación está desactivada, pero si la establece, la referencia principal a la entidad principal estará disponible para el tipo de parte integrada.

    Como resultado, tenemos el siguiente modelo:

    NotaR: Si define el tipo de colección de propiedades de navegación como Colocar, es muy importante implementar correctamente Equals () y GetHashCode () para las clases que se ajustan a los tipos complejos del modelo. Para crear estos métodos usando la plantilla Entity Developer, seleccione el nodo de plantilla en el árbol de objetos Líder modelo caja de herramientas, seleccione Implementar Igual propiedad de plantilla en Propiedades caja de herramientas e instalarlo Cierto.

    El código generado para el modelo se verá así:

        
    
        /// <summary>
        /// There are no comments for Dept in the schema.
        /// </summary>
        public partial class Dept {
    
            private int _DEPTNO;
    
            private string _DNAME;
    
            private string _LOC;
    
            private Iesi.Collections.Generic.ISet<PartialEmpType> _PartialEmpTypes;
    
            #region Extensibility Method Definitions
    
            partial void OnCreated();
    
            public override bool Equals(object obj)
            {
              Dept toCompare = obj as Dept;
              if (toCompare == null)
              {
                return false;
              }
    
              if (!Object.Equals(this.DEPTNO, toCompare.DEPTNO))
                return false;
    
              return true;
            }
    
            public override int GetHashCode()
            {
              int hashCode = 13;
              hashCode = (hashCode * 7) + DEPTNO.GetHashCode();
              return hashCode;
            }
    
            #endregion
    
            public Dept()
            {
                this._PartialEmpTypes = new Iesi.Collections.Generic.HashedSet<PartialEmpType>();
                OnCreated();
            }
    
            /// <summary>
            /// There are no comments for DEPTNO in the schema.
            /// </summary>
            public virtual int DEPTNO
            {
                get
                {
                    return this._DEPTNO;
                }
                set
                {
                    this._DEPTNO = value;
                }
            }
    
            /// <summary>
            /// There are no comments for DNAME in the schema.
            /// </summary>
            public virtual string DNAME
            {
                get
                {
                    return this._DNAME;
                }
                set
                {
                    this._DNAME = value;
                }
            }
    
            /// <summary>
            /// There are no comments for LOC in the schema.
            /// </summary>
            public virtual string LOC
            {
                get
                {
                    return this._LOC;
                }
                set
                {
                    this._LOC = value;
                }
            }
    
            /// <summary>
            /// There are no comments for PartialEmpTypes in the schema.
            /// </summary>
            public virtual Iesi.Collections.Generic.ISet<PartialEmpType> PartialEmpTypes
            {
                get
                {
                    return this._PartialEmpTypes;
                }
                set
                {
                    this._PartialEmpTypes = value;
                }
            }
        }
    
        /// <summary>
        /// There are no comments for PartialEmpType in the schema.
        /// </summary>
        public partial class PartialEmpType {
    
            private string _ENAME;
    
            private string _JOB;
    
            private System.Nullable<int> _MGR;
    
            #region Extensibility Method Definitions
    
            partial void OnCreated();
    
            public override bool Equals(object obj)
            {
              PartialEmpType toCompare = obj as PartialEmpType;
              if (toCompare == null)
              {
                return false;
              }
    
              if (!Object.Equals(this.ENAME, toCompare.ENAME))
                return false;
              if (!Object.Equals(this.JOB, toCompare.JOB))
                return false;
              if (!Object.Equals(this.MGR, toCompare.MGR))
                return false;
    
              return true;
            }
    
            public override int GetHashCode()
            {
              int hashCode = 13;
              return hashCode;
            }
    
            #endregion
    
            public PartialEmpType()
            {
                OnCreated();
            }
    
            /// <summary>
            /// There are no comments for ENAME in the schema.
            /// </summary>
            public virtual string ENAME
            {
                get
                {
                    return this._ENAME;
                }
                set
                {
                    this._ENAME = value;
                }
            }
    
            /// <summary>
            /// There are no comments for JOB in the schema.
            /// </summary>
            public virtual string JOB
            {
                get
                {
                    return this._JOB;
                }
                set
                {
                    this._JOB = value;
                }
            }
    
            /// <summary>
            /// There are no comments for MGR in the schema.
            /// </summary>
            public virtual System.Nullable<int> MGR
            {
                get
                {
                    return this._MGR;
                }
                set
                {
                    this._MGR = value;
                }
            }
        }

    Como se puede ver en el código anterior, la propiedad se genera en la clase de entidad principal, que contiene una referencia a la colección de instancias de la clase de tipo de parte compleja.

    El mapeo creado para el tema del Departamento se ve así:

    <hibernate-mapping namespace="testmodellerModel" xmlns="urn:nhibernate-mapping-2.2">
      <class name="Dept" table="Dept" schema="dbo">
        <id name="DEPTNO" type="Int32">
          <column name="DEPTNO" not-null="true" precision="10" scale="0" sql-type="int" />
          <generator class="assigned" />
        </id>
        <property name="DNAME" type="String">
          <column name="DNAME" not-null="false" length="14" sql-type="varchar" />
        </property>
        <property name="LOC" type="String">
          <column name="LOC" not-null="false" length="13" sql-type="varchar" />
        </property>
        <set name="PartialEmpTypes" table="Dept_PartialEmpTypes" generic="true">
          <key>
            <column name="DEPTNO" not-null="true" precision="10" scale="0" sql-type="int" />
          </key>
          <composite-element class="PartialEmpType">
            <property name="ENAME">
              <column name="ENAME" not-null="false" length="10" sql-type="varchar" />
            </property>
            <property name="JOB">
              <column name="JOB" not-null="false" length="9" sql-type="varchar" />
            </property>
            <property name="MGR">
              <column name="MGR" not-null="false" precision="10" scale="0" sql-type="int" />
            </property>
          </composite-element>
        </set>
      </class>
    </hibernate-mapping>

    El modelo NHibernate para Entity Developer discutido en este ejemplo se puede descargar aquí.

    Mostrar colecciones de componentes para la asociación de muchos a muchos:

    Las asociaciones de muchos a muchos usan una tabla intermedia que tiene una clave externa a las tablas de ambos objetos relacionados. Un objeto utiliza varios objetos de otro tipo, y uno de estos últimos objetos se refiere a varios objetos del primer tipo. Como siempre para las comparaciones de muchos a muchos en las bases de datos relacionales, necesitamos una tercera tabla que proporcione enlaces a las relaciones de muchos a muchos. Esta asignación le permite asignar columnas adicionales de la tabla de agregación "muchos a muchos" a un tipo complejo. Ejemplo: La base de datos contiene tablas de Empleados, Territorios y EmployeeTerritories; este último proporciona enlaces a relaciones de muchos a muchos. La tabla EmployeeTerritories contiene 1 columna adicional, que es EmployeeTerritoriesDescription. diagrama de base de datos
    Realice la siguiente secuencia de operaciones:

    • crear un modelo NHibernate;
    • agregar tablas de Empleados, Territorios y EmployeeTerritories;
    • seleccione la propiedad EmployeeTerritoriesDescription de la entidad EmployeeTerritories y arrástrela a un tipo complejo separado, asígnele el nombre "EmployeeTerritoriesExtra", elimine el objeto EmployeeTerritor;
    • luego agregamos una relación muchos a muchos entre las entidades Empleado y Territorio y la configuramos como se muestra en la captura de pantalla:

    Redactor de la Asociación
    У Redactor de la Asociación cuadro de diálogo únete a la mesa el campo de entrada se especifica mediante el nombre de la tabla de asociación, que también proporciona enlaces a la relación de muchos a muchos Esquema el nombre del esquema en el que existe se ingresa en el campo. En el cuadro de diálogo, debe especificar el nombre de la columna de clave externa de la tabla de combinación, que proporciona enlaces a muchas relaciones. Para establecer la asignación de la tabla de combinación, campos adicionales para combinar "muchos a muchos" en Componente campo con Redactor de la Asociación el cuadro de diálogo especifica el tipo complejo requerido, que contiene un conjunto de propiedades correspondientes a un conjunto de campos adicionales en la tabla de combinación. Este cuadro de diálogo también le permite definir una asignación privada para propiedades de tipo complejo para adjuntar campos de tabla adicionales si esta asignación de asociación es diferente de la asignación general de propiedades de tipo complejo. Como resultado, tenemos el siguiente modelo:
    Modelo de datos
    NotaR: Si define el tipo de colección de propiedades de navegación como Colocar, es muy importante implementar correctamente Equals () y GetHashCode () para las clases que se ajustan a los tipos complejos del modelo. Para crear estos métodos usando la plantilla Entity Developer, seleccione el nodo de plantilla en el árbol de objetos Líder modelo caja de herramientas, seleccione Implementar Igual propiedad de plantilla en Propiedades caja de herramientas e instalarlo Cierto. El código generado para el modelo se verá así:

       
        /// <summary>
        /// There are no comments for Territory in the schema.
        /// </summary>
        public partial class Territory {
    
            private string _TerritoryID;
    
            private string _TerritoryDescription;
    
            private Iesi.Collections.Generic.ISet<EmployeeTerritoriesExtra> _Employees;
    
            #region Extensibility Method Definitions
    
            partial void OnCreated();
    
            public override bool Equals(object obj)
            {
              Territory toCompare = obj as Territory;
              if (toCompare == null)
              {
                return false;
              }
    
              if (!Object.Equals(this.TerritoryID, toCompare.TerritoryID))
                return false;
    
              return true;
            }
    
            public override int GetHashCode()
            {
              int hashCode = 13;
              hashCode = (hashCode * 7) + TerritoryID.GetHashCode();
              return hashCode;
            }
    
            #endregion
    
            public Territory()
            {
                this._Employees = new Iesi.Collections.Generic.HashedSet<EmployeeTerritoriesExtra>();
                OnCreated();
            }
    
            /// <summary>
            /// There are no comments for TerritoryID in the schema.
            /// </summary>
            public virtual string TerritoryID
            {
                get
                {
                    return this._TerritoryID;
                }
                set
                {
                    this._TerritoryID = value;
                }
            }
    
            /// <summary>
            /// There are no comments for TerritoryDescription in the schema.
            /// </summary>
            public virtual string TerritoryDescription
            {
                get
                {
                    return this._TerritoryDescription;
                }
                set
                {
                    this._TerritoryDescription = value;
                }
            }
    
            /// <summary>
            /// There are no comments for Employees in the schema.
            /// </summary>
            public virtual Iesi.Collections.Generic.ISet<EmployeeTerritoriesExtra> Employees
            {
                get
                {
                    return this._Employees;
                }
                set
                {
                    this._Employees = value;
                }
            }
        }
    
        /// <summary>
        /// There are no comments for Employee in the schema.
        /// </summary>
        public partial class Employee {
    
            private int _EmployeeID;
    
            private string _LastName;
    
            private string _FirstName;
    
            private System.Nullable<System.DateTime> _BirthDate;
    
            private System.Nullable<System.DateTime> _HireDate;
    
            private string _Address;
    
            private Iesi.Collections.Generic.ISet<EmployeeTerritoriesExtra> _Territories;
    
            #region Extensibility Method Definitions
    
            partial void OnCreated();
    
            public override bool Equals(object obj)
            {
              Employee toCompare = obj as Employee;
              if (toCompare == null)
              {
                return false;
              }
    
              if (!Object.Equals(this.EmployeeID, toCompare.EmployeeID))
                return false;
    
              return true;
            }
    
            public override int GetHashCode()
            {
              int hashCode = 13;
              hashCode = (hashCode * 7) + EmployeeID.GetHashCode();
              return hashCode;
            }
    
            #endregion
    
            public Employee()
            {
                this._Territories = new Iesi.Collections.Generic.HashedSet<EmployeeTerritoriesExtra>();
                OnCreated();
            }
    
            /// <summary>
            /// There are no comments for EmployeeID in the schema.
            /// </summary>
            public virtual int EmployeeID
            {
                get
                {
                    return this._EmployeeID;
                }
                set
                {
                    this._EmployeeID = value;
                }
            }
    
            /// <summary>
            /// There are no comments for LastName in the schema.
            /// </summary>
            public virtual string LastName
            {
                get
                {
                    return this._LastName;
                }
                set
                {
                    this._LastName = value;
                }
            }
    
            /// <summary>
            /// There are no comments for FirstName in the schema.
            /// </summary>
            public virtual string FirstName
            {
                get
                {
                    return this._FirstName;
                }
                set
                {
                    this._FirstName = value;
                }
            }
    
            /// <summary>
            /// There are no comments for BirthDate in the schema.
            /// </summary>
            public virtual System.Nullable<System.DateTime> BirthDate
            {
                get
                {
                    return this._BirthDate;
                }
                set
                {
                    this._BirthDate = value;
                }
            }
    
            /// <summary>
            /// There are no comments for HireDate in the schema.
            /// </summary>
            public virtual System.Nullable<System.DateTime> HireDate
            {
                get
                {
                    return this._HireDate;
                }
                set
                {
                    this._HireDate = value;
                }
            }
    
            /// <summary>
            /// There are no comments for Address in the schema.
            /// </summary>
            public virtual string Address
            {
                get
                {
                    return this._Address;
                }
                set
                {
                    this._Address = value;
                }
            }
    
            /// <summary>
            /// There are no comments for Territories in the schema.
            /// </summary>
            public virtual Iesi.Collections.Generic.ISet<EmployeeTerritoriesExtra> Territories
            {
                get
                {
                    return this._Territories;
                }
                set
                {
                    this._Territories = value;
                }
            }
        }
    
        /// <summary>
        /// There are no comments for EmployeeTerritoriesExtra in the schema.
        /// </summary>
        public partial class EmployeeTerritoriesExtra {
    
            private string _EmployeeTerritoriesDescription;
    
            #region Extensibility Method Definitions
    
            partial void OnCreated();
    
            public override bool Equals(object obj)
            {
              EmployeeTerritoriesExtra toCompare = obj as EmployeeTerritoriesExtra;
              if (toCompare == null)
              {
                return false;
              }
    
              if (!Object.Equals(this.EmployeeTerritoriesDescription, toCompare.EmployeeTerritoriesDescription))
                return false;
    
              return true;
            }
    
            public override int GetHashCode()
            {
              int hashCode = 13;
              return hashCode;
            }
    
            #endregion
    
            public EmployeeTerritoriesExtra()
            {
                OnCreated();
            }
    
            /// <summary>
            /// There are no comments for EmployeeTerritoriesDescription in the schema.
            /// </summary>
            public virtual string EmployeeTerritoriesDescription
            {
                get
                {
                    return this._EmployeeTerritoriesDescription;
                }
                set
                {
                    this._EmployeeTerritoriesDescription = value;
                }
            }
    
            #region Ends of the many-to-many association 'Employee_Territory'
    
            /// <summary>
            /// There are no comments for Employees in the schema.
            /// </summary>
            public Employee Employees
            {
                get;
                set;
            }
    
            /// <summary>
            /// There are no comments for Territories in the schema.
            /// </summary>
            public Territory Territories
            {
                get;
                set;
            }
    
            #endregion
        }

    Como se puede ver en el código anterior, en las clases que corresponden a entidades relacionadas con la asociación "muchos a muchos", se genera una propiedad que contiene una referencia a una colección de clases para un tipo complejo, que a su vez consiste en un conjunto de propiedades correspondientes a un conjunto de campos de tabla de combinación adicionales. Nuevamente, en una clase de tipos complejos, se generan referencias a clases que corresponden a objetos asociados con la asociación muchos a muchos. Así, cuando una asociación de muchos a muchos se organiza de esta manera, tenemos acceso tanto a los valores de las columnas adicionales de la tabla de unión haciendo referencia a los campos de tipo complejo como a las instancias de las clases de relación haciendo referencia a al campo de referencia relevante del tipo complejo.

    El mapeo creado para Empleado y Territorio se ve así:

    <hibernate-mapping namespace="testmodellerModel" xmlns="urn:nhibernate-mapping-2.2">
      <class name="Territory" table="Territories" schema="ManyToManyExtra">
        <id name="TerritoryID" type="String">
          <column name="TerritoryID" not-null="true" length="20" sql-type="nvarchar" />
          <generator class="assigned" />
        </id>
        <property name="TerritoryDescription" type="String">
          <column name="TerritoryDescription" not-null="true" length="50" sql-type="nchar" />
        </property>
        <set name="Employees" table="EmployeeTerritories" schema="ManyToManyExtra" generic="true">
          <key>
            <column name="TerritoryID" not-null="true" length="20" sql-type="nvarchar" />
          </key>
          <composite-element class="EmployeeTerritoriesExtra">
            <many-to-one name="Employees" class="Employee" fetch="join">
              <column name="EmployeeID" not-null="true" precision="10" scale="0" sql-type="int" />
            </many-to-one>
            <property name="EmployeeTerritoriesDescription">
              <column name="EmployeeTerritoriesDescription" not-null="false" length="50" sql-type="nvarchar" />
            </property>
          </composite-element>
        </set>
      </class>
    </hibernate-mapping>

    El modelo NHibernate para Entity Developer discutido en este ejemplo se puede descargar aquí.

    Artículos de interés

    Subir