Soporte para mostrar "muchos a muchos" para las propiedades de navegación de componentes en Entity Developer

Este artículo explica y proporciona un ejemplo práctico de cómo se implementa la compatibilidad con las propiedades de navegación de componentes en Entity Developer para NHibernate.
El soporte para esta funcionalidad incluye la capacidad de desconectarse a un tipo complejo para una mayor reutilización no solo de las propiedades de la entidad escalar sino también de las propiedades de navegación seguidas de un mapeo de visualización completo en el nivel de mapeo de propiedad específico de la propiedad privada con un tipo igual a un tipo específico de entidad compleja.

Hay varias formas de mostrar las propiedades de navegación de los componentes en NHibernate:

  • Lotes a uno;
  • Uno a muchos;
  • el uno al otro;
  • Muchos a muchos.

En este artículo, veremos cómo mapear las propiedades de navegación de componentes de muchos a muchos.
Para obtener más información sobre otros tipos de propiedades de navegación de componentes de visualización, consulte el artículo dedicado a ellos aquí.

Índice

    Muestre las propiedades de navegación de muchos a muchos componentes:

    Este tipo de mapeo puede ser efectivo si el modelo tiene múltiples objetos asociados con asociaciones de muchos a muchos con la misma entidad, y posiblemente (pero no necesariamente) tenga algún conjunto de propiedades similares por significado y estructura.

    Luego, después de crear el modelo, tiene sentido asignar un conjunto similar de propiedades escalares y de navegación correspondientes a un tipo complejo separado y reemplazar cada conjunto en los objetos con una propiedad que tenga un tipo igual al tipo complejo y una configuración de mapeo privado adecuada. por esa propiedad.

    Ejemplo:

    La base de datos contiene las tablas Companies, Factories y CompanyFactories, esta última proporciona enlaces a la relación “muchos a muchos” entre las tablas Companies y Factory.
    La base de datos también contiene las tablas Shops y CompanyShops, esta última también proporciona enlaces a la relación "muchos a muchos" entre las tablas Companies y Shops.

    El script para crear tablas para DBMS de SQL Server tiene este aspecto:

    CREATE SCHEMA ManyToMany;
    GO
    
    CREATE TABLE ManyToMany.Companies (
      CompanyID int,
      CompanyName nvarchar(15) COLLATE Cyrillic_General_CI_AS NOT NULL,
      CONSTRAINT PK_Companies PRIMARY KEY (CompanyID)
    )
    GO
    
    CREATE TABLE ManyToMany.Factories (
      FactoryID int,
      FactoryName nvarchar(15) COLLATE Cyrillic_General_CI_AS NOT NULL,
      FactoryAddress nvarchar(60) COLLATE Cyrillic_General_CI_AS NULL,
      FactoryCity nvarchar(15) COLLATE Cyrillic_General_CI_AS NULL,
      FactoryRegion nvarchar(15) COLLATE Cyrillic_General_CI_AS NULL,
      FactoryPostalCode nvarchar(10) COLLATE Cyrillic_General_CI_AS NULL,
      FactoryCountry nvarchar(15) COLLATE Cyrillic_General_CI_AS NULL,
      WorkersCount int,
      CONSTRAINT PK_Factories PRIMARY KEY (FactoryID)
    )
    GO
    
    CREATE TABLE ManyToMany.Shops (
      ShopID int,
      ShopName nvarchar(15) COLLATE Cyrillic_General_CI_AS NOT NULL,
      ShopAddress nvarchar(60) COLLATE Cyrillic_General_CI_AS NULL,
      ShopCity nvarchar(15) COLLATE Cyrillic_General_CI_AS NULL,
      ShopRegion nvarchar(15) COLLATE Cyrillic_General_CI_AS NULL,
      ShopPostalCode nvarchar(10) COLLATE Cyrillic_General_CI_AS NULL,
      ShopCountry nvarchar(15) COLLATE Cyrillic_General_CI_AS NULL,
      CONSTRAINT PK_Shops PRIMARY KEY (ShopID)
    )
    GO
    
    CREATE TABLE ManyToMany.CompanyFactories (
      CompanyID int NOT NULL,
      FactoryID int NOT NULL,
      PRIMARY KEY (CompanyID, FactoryID),
      FOREIGN KEY (CompanyID) REFERENCES ManyToMany.Companies (CompanyID),
      FOREIGN KEY (FactoryID) REFERENCES ManyToMany.Factories (FactoryID)
    )
    GO
    
    CREATE TABLE ManyToMany.CompanyShops (
      CompanyID int NOT NULL,
      ShopID int NOT NULL,
      PRIMARY KEY (CompanyID, ShopID),
      FOREIGN KEY (CompanyID) REFERENCES ManyToMany.Companies (CompanyID),
      FOREIGN KEY (ShopID) REFERENCES ManyToMany.Shops (ShopID)
    )
    GO

    El gráfico de la tabla se ve así:

    Diagrama

    Realice la siguiente secuencia de operaciones:

    • crear un modelo NHibernate;
    • agregue a las tablas del modelo Empresas, Fábricas, Tiendas, EmpresaFábrica y EmpresaTiendas.

    Antes de definir un tipo complejo, el modelo se ve así:

    El modelo inicial

    Seleccionamos las propiedades ShopAddress, ShopCity, ShopRegion, ShopPostalCode, ShopCountry y la propiedad Navigation de la esencia de la empresa Shop, las arrastramos a un tipo complejo separado y lo llamamos 'ContractorType'; hay una conexión entre este tipo complejo y la clase Company, y de ahora en adelante es un tipo ContractorType complejo que contiene la propiedad de navegación Companies, y en lugar de un conjunto de propiedades movidas, la entidad Shop contiene una propiedad con un tipo igual a ContractorType , llamémoslo Contratistas. Esto es opcional, pero por comodidad eliminamos el prefijo Shop de los nombres de propiedad y las columnas del tipo ContractorType complejo en la visualización predeterminada.

    La relación entre ContractorType y el objeto Store es la siguiente:

    La ventana Editor de asociaciones para la asociación.

    Como se puede ver desde Redactor de la Asociación cuadro de diálogo, parte de la configuración de la relación está en la propia asociación, para el caso de "muchos a muchos" también hay una asignación predeterminada para la columna de clave externa de la tabla de unión para el objeto que contendrá la propiedad del tipo complejo especificado , pero si es necesario, se puede cambiar de forma personalizada para una entidad de propiedad específica. Esto se mostrará en nuestro ejemplo más adelante en este artículo.

    Debido a que creamos un tipo complejo basado en el conjunto de propiedades del objeto Shop, la visualización personalizada de estas propiedades se determinó automáticamente para este objeto durante la operación de arrastrar y soltar y se ve así:

    Mostrar las propiedades de los objetos de la tienda

    Ahora debe eliminar el vínculo entre la empresa y los objetos Factory, así como eliminar las propiedades FactoryAddress, FactoryCity, FactoryRegion, FactoryPostalCode, FactoryCountry para el objeto Factory. En lugar de estos conjuntos de propiedades que describen la dirección y la lista de bienes de contraparte, debe agregar una propiedad con el nombre "Contractor" y un tipo igual a ContractorType. Luego debe establecer una asignación personalizada para la propiedad Contratista del objeto Fábricas en las columnas de la tabla Fábricas, como se muestra a continuación:

    Visualización personalizada de la propiedad del contratista

    Como resultado, tenemos el siguiente modelo:

    el modelo definitivo

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

        /// <summary>
        /// There are no comments for ContractorType in the schema.
        /// </summary>
        public partial class ContractorType {
            private string _Address;
            private string _City;
            private string _Region;
            private string _Code;
            private string _Country;
            private Iesi.Collections.Generic.ISet<Company> _Companies;    
            #region Extensibility Method Definitions        
            partial void OnCreated();        
            #endregion
            public ContractorType()
            {
                this._Companies = new Iesi.Collections.Generic.HashedSet<Company>();
                OnCreated();
            }    
            /// <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 City in the schema.
            /// </summary>
            public virtual string City
            {
                get
                {
                    return this._City;
                }
                set
                {
                    this._City = value;
                }
            }    
            /// <summary>
            /// There are no comments for Region in the schema.
            /// </summary>
            public virtual string Region
            {
                get
                {
                    return this._Region;
                }
                set
                {
                    this._Region = value;
                }
            }    
            /// <summary>
            /// There are no comments for Code in the schema.
            /// </summary>
            public virtual string Code
            {
                get
                {
                    return this._Code;
                }
                set
                {
                    this._Code = value;
                }
            }    
            /// <summary>
            /// There are no comments for Country in the schema.
            /// </summary>
            public virtual string Country
            {
                get
                {
                    return this._Country;
                }
                set
                {
                    this._Country = value;
                }
            }    
            /// <summary>
            /// There are no comments for Companies in the schema.
            /// </summary>
            public virtual Iesi.Collections.Generic.ISet<Company> Companies
            {
                get
                {
                    return this._Companies;
                }
                set
                {
                    this._Companies = value;
                }
            }
        }    
        /// <summary>
        /// There are no comments for Company in the schema.
        /// </summary>
        public partial class Company {
            private int _CompanyID;
            private string _CompanyName;    
            #region Extensibility Method Definitions        
            partial void OnCreated();        
            #endregion
            public Company()
            {
                OnCreated();
            }    
            /// <summary>
            /// There are no comments for CompanyID in the schema.
            /// </summary>
            public virtual int CompanyID
            {
                get
                {
                    return this._CompanyID;
                }
                set
                {
                    this._CompanyID = value;
                }
            }    
            /// <summary>
            /// There are no comments for CompanyName in the schema.
            /// </summary>
            public virtual string CompanyName
            {
                get
                {
                    return this._CompanyName;
                }
                set
                {
                    this._CompanyName = value;
                }
            }
        }
        /// <summary>
        /// There are no comments for Shop in the schema.
        /// </summary>
        public partial class Shop {
            private int _ShopID;
            private string _ShopName;
            private ContractorType _Contractor;    
            #region Extensibility Method Definitions        
            partial void OnCreated();        
            #endregion
            public Shop()
            {
                this._Contractor = new ContractorType();
                OnCreated();
            }    
            /// <summary>
            /// There are no comments for ShopID in the schema.
            /// </summary>
            public virtual int ShopID
            {
                get
                {
                    return this._ShopID;
                }
                set
                {
                    this._ShopID = value;
                }
            }    
            /// <summary>
            /// There are no comments for ShopName in the schema.
            /// </summary>
            public virtual string ShopName
            {
                get
                {
                    return this._ShopName;
                }
                set
                {
                    this._ShopName = value;
                }
            }    
            /// <summary>
            /// There are no comments for Contractor in the schema.
            /// </summary>
            public virtual ContractorType Contractor
            {
                get
                {
                    return this._Contractor;
                }
                set
                {
                    this._Contractor = value;
                }
            }
        }
        /// <summary>
        /// There are no comments for Factory in the schema.
        /// </summary>
        public partial class Factory {
            private int _FactoryID;
            private string _FactoryName;
            private System.Nullable<int> _WorkersCount;
            private ContractorType _Contractor;    
            #region Extensibility Method Definitions        
            partial void OnCreated();        
            #endregion
            public Factory()
            {
                this._Contractor = new ContractorType();
                OnCreated();
            }    
            /// <summary>
            /// There are no comments for FactoryID in the schema.
            /// </summary>
            public virtual int FactoryID
            {
                get
                {
                    return this._FactoryID;
                }
                set
                {
                    this._FactoryID = value;
                }
            }    
            /// <summary>
            /// There are no comments for FactoryName in the schema.
            /// </summary>
            public virtual string FactoryName
            {
                get
                {
                    return this._FactoryName;
                }
                set
                {
                    this._FactoryName = value;
                }
            }    
            /// <summary>
            /// There are no comments for WorkersCount in the schema.
            /// </summary>
            public virtual System.Nullable<int> WorkersCount
            {
                get
                {
                    return this._WorkersCount;
                }
                set
                {
                    this._WorkersCount = value;
                }
            }    
            /// <summary>
            /// There are no comments for Contractor in the schema.
            /// </summary>
            public virtual ContractorType Contractor
            {
                get
                {
                    return this._Contractor;
                }
                set
                {
                    this._Contractor = value;
                }
            }
        }

    Como puede ver en el código generado, la clase ContractorType genera una propiedad que hace referencia a la clase Company, y las clases Shop y Factory, a su vez, contienen una propiedad Contractor con un tipo igual a ContractorType, y estas propiedades describen el fabricante y el distribuidor. direcciones de productos y listas pronunciar respectivamente.

    El mapeo Xml creado para el modelo se ve así:

    <hibernate-mapping namespace="testmodellerModel" xmlns="urn:nhibernate-mapping-2.2">
      <class name="Company" table="Companies" schema="ManyToMany">
        <id name="CompanyID" type="Int32">
          <column name="CompanyID" not-null="true" precision="10" scale="0" sql-type="int" />
          <generator class="assigned" />
        </id>
        <property name="CompanyName" type="String">
          <column name="CompanyName" not-null="true" length="15" sql-type="nvarchar" />
        </property>
      </class>
      <class name="Factory" table="Factories" schema="ManyToMany">
        <id name="FactoryID" type="Int32">
          <column name="FactoryID" not-null="true" precision="10" scale="0" sql-type="int" />
          <generator class="assigned" />
        </id>
        <property name="FactoryName" type="String">
          <column name="FactoryName" not-null="true" length="15" sql-type="nvarchar" />
        </property>
        <property name="WorkersCount" type="Int32">
          <column name="WorkersCount" not-null="false" precision="10" scale="0" sql-type="int" />
        </property>
        <component name="Contractor" class="ContractorType">
          <property name="Address" type="String">
            <column name="FactoryAddress" not-null="false" length="60" sql-type="nvarchar" />
          </property>
          <property name="City" type="String">
            <column name="FactoryCity" not-null="false" length="15" sql-type="nvarchar" />
          </property>
          <property name="Region" type="String">
            <column name="FactoryRegion" not-null="false" length="15" sql-type="nvarchar" />
          </property>
          <property name="Code" type="String">
            <column name="FactoryPostalCode" not-null="false" length="10" sql-type="nvarchar" />
          </property>
          <property name="Country" type="String">
            <column name="FactoryCountry" not-null="false" length="15" sql-type="nvarchar" />
          </property>
          <set name="Companies" table="CompanyFactories" schema="ManyToMany" generic="true">
            <key>
              <column name="FactoryID" not-null="true" precision="10" scale="0" sql-type="int" />
            </key>
            <many-to-many class="Company" fetch="join">
              <column name="CompanyID" not-null="true" precision="10" scale="0" sql-type="int" />
            </many-to-many>
          </set>
        </component>
      </class>
      <class name="Shop" table="Shops" schema="ManyToMany">
        <id name="ShopID" type="Int32">
          <column name="ShopID" not-null="true" precision="10" scale="0" sql-type="int" />
          <generator class="assigned" />
        </id>
        <property name="ShopName" type="String">
          <column name="ShopName" not-null="true" length="15" sql-type="nvarchar" />
        </property>
        <component name="Contractor" class="ContractorType">
          <property name="Address" type="String">
            <column name="ShopAddress" not-null="false" length="60" sql-type="nvarchar" />
          </property>
          <property name="City" type="String">
            <column name="ShopCity" not-null="false" length="15" sql-type="nvarchar" />
          </property>
          <property name="Region" type="String">
            <column name="ShopRegion" not-null="false" length="15" sql-type="nvarchar" />
          </property>
          <property name="Code" type="String">
            <column name="ShopPostalCode" not-null="false" length="10" sql-type="nvarchar" />
          </property>
          <property name="Country" type="String">
            <column name="ShopCountry" not-null="false" length="15" sql-type="nvarchar" />
          </property>
          <set name="Companies" table="CompanyShops" schema="ManyToMany" generic="true">
            <key>
              <column name="ShopID" not-null="true" precision="10" scale="0" sql-type="int" />
            </key>
            <many-to-many class="Company" fetch="join">
              <column name="CompanyID" not-null="true" precision="10" scale="0" sql-type="int" />
            </many-to-many>
          </set>
        </component>
      </class>
    </hibernate-mapping>

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

    Artículos de interés

    Subir