La mejor manera de modelo de Muchos-A-Uno, las Relaciones en NHibernate Cuando se Trata de un Legado de DB?

StackOverflow https://stackoverflow.com/questions/10915

  •  08-06-2019
  •  | 
  •  

Pregunta

Advertencia - soy muy nuevo en Fluent.Sé que esta pregunta parece simple - y estoy seguro de que hay una respuesta simple, pero he estado haciendo girar mis ruedas durante algún tiempo en esto.Estoy tratando con un legado db que realmente no puede ser alterado estructuralmente.Tengo una tabla de detalles que las listas de los planes de pago que ha sido aceptada por un cliente.Cada plan de pago tiene un ID que se vincula a una tabla de referencia para obtener el plan de los términos, condiciones, etc.En mi modelo de objetos, tengo una AcceptedPlan clase, y un Plan de clase.Originalmente, he usado muchos-a-uno de la tabla de detalle de regreso a la tabla de referencia para el modelo de esta relación en Fluent.También he creado una relación de uno a muchos relación va en la dirección opuesta desde el Plan de clase a la AcceptedPlan clase.Esto estaba bien, mientras que yo era la simple lectura de los datos.Yo podría ir a mi Plan de objeto, que era propiedad de mi AcceptedPlan clase para leer el plan de detalles.Mi problema surgió cuando tuve que empezar a insertar nuevas filas a la tabla de detalles.Desde mi lectura, parece ser que la única forma de crear un nuevo objeto secundario es agregar a los padres de objeto y, a continuación, guardar la sesión.Pero yo no quiero tener que crear un nuevo padre objeto del Plan cada vez que quiero crear un nuevo registro de detalle.Esto parece como una sobrecarga innecesaria.¿Alguien sabe si voy sobre esto en el camino equivocado?

¿Fue útil?

Solución

Me gustaría alejarse de tener hijos objeto que contiene sus lógicas de los padres, puede llegar a ser muy complicado y muy recursiva con bastante rapidez cuando haces eso.Me gustaría echar un vistazo a cómo está tratando de utilizar el modelo de dominio antes de hacer ese tipo de cosas.Usted puede fácilmente tener todavía la IDENTIFICACIÓN de las referencias en las tablas y acaba de salir de ellos no asignados.

Aquí están dos ejemplos de asignaciones que pueden empujar en la dirección correcta, he tenido que adlib los nombres de tabla, etc, pero eso podría ayudar.Yo probablemente también sugieren la asignación de la StatusId a una enumeración.

Preste atención a la forma de la bolsa efectivo mapas de la tabla de detalles en una colección.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2">
    <class lazy="false" name="Namespace.Customer, Namespace" table="Customer">
        <id name="Id" type="Int32" unsaved-value="0">
            <column name="CustomerAccountId" length="4" sql-type="int" not-null="true" unique="true" index="CustomerPK"/>
            <generator class="native" />
        </id>

        <bag name="AcceptedOffers" inverse="false" lazy="false" cascade="all-delete-orphan" table="details">
          <key column="CustomerAccountId" foreign-key="AcceptedOfferFK"/>
          <many-to-many
            class="Namespace.AcceptedOffer, Namespace"
            column="AcceptedOfferFK"
            foreign-key="AcceptedOfferID"
            lazy="false"
           />
        </bag>

  </class>
</hibernate-mapping>


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2">
    <class lazy="false" name="Namespace.AcceptedOffer, Namespace" table="AcceptedOffer">
        <id name="Id" type="Int32" unsaved-value="0">
            <column name="AcceptedOfferId" length="4" sql-type="int" not-null="true" unique="true" index="AcceptedOfferPK"/>
            <generator class="native" />
        </id>

        <many-to-one 
          name="Plan"
          class="Namespace.Plan, Namespace"
          lazy="false"
          cascade="save-update"
        >
        <column name="PlanFK" length="4" sql-type="int" not-null="false"/>
        </many-to-one>

        <property name="StatusId" type="Int32">
            <column name="StatusId" length="4" sql-type="int" not-null="true"/>
        </property>

  </class>
</hibernate-mapping>

Otros consejos

No ver su diagrama de base de datos, mientras que yo estaba escribiendo.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2">
    <class lazy="false" name="Namespace.Customer, Namespace" table="Customer">
        <id name="Id" type="Int32" unsaved-value="0">
            <column name="customer_id" length="4" sql-type="int" not-null="true" unique="true" index="CustomerPK"/>
            <generator class="native" />
        </id>

        <bag name="AcceptedOffers" inverse="false" lazy="false" cascade="all-delete-orphan">
            <key column="accepted_offer_id"/>
            <one-to-many class="Namespace.AcceptedOffer, Namespace"/>
        </bag>

  </class>
</hibernate-mapping>


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2">
    <class lazy="false" name="Namespace.AcceptedOffer, Namespace" table="Accepted_Offer">
        <id name="Id" type="Int32" unsaved-value="0">
            <column name="accepted_offer_id" length="4" sql-type="int" not-null="true" unique="true" />
            <generator class="native" />
        </id>

        <many-to-one name="Plan" class="Namespace.Plan, Namespace" lazy="false" cascade="save-update">
            <column name="plan_id" length="4" sql-type="int" not-null="false"/>
        </many-to-one>

  </class>
</hibernate-mapping>

Probablemente debería hacer el truco (sólo he hecho el ejemplo de las asignaciones para las colecciones, tendrás que añadir otras propiedades).

El enfoque me gustaría tener a este modelo es la siguiente:

Objeto de cliente contiene un ICollection <PaymentPlan> PaymentPlans que representan los planes que el cliente ha aceptado.

El PaymentPlan para que el Cliente se asignan utilizando una bolsa que se utiliza la tabla de detalles para establecer la id de cliente asignado a la que PaymentPlans.El uso de cascada de todos-delete-orphan, si el cliente se ha eliminado, tanto las entradas de los detalles y la PaymentPlans que sean propiedad del cliente será suprimido.

El PaymentPlan objeto contiene un PlanTerms objeto que representa las condiciones del plan de pago.

El PlanTerms se asignan a un PaymentPlan el uso de muchos-a-uno la asignación de cascada de guardar en la actualización que acaba de insertar una referencia a la correspondiente PlanTerms objeto en el PaymentPlan.

Utilizando este modelo, se podría crear PlanTerms de forma independiente y, a continuación, cuando se agrega un nuevo PaymentPlan a un cliente, usted debería crear una nueva PaymentPlan objeto pasando en el correspondiente PlanTerms objeto y, a continuación, agregar a la colección en el Cliente en cuestión.Finalmente, te gustaría guardar el Cliente y dejar que nhibernate cascada de la operación de guardar.

Se acabaría con un objeto de Cliente, un PaymentPlan objeto y un PlanTerms objeto con el Cliente (tabla clientes) poseer instancias de PaymentPlans (la tabla de detalles) que todos los adhear específicos PlanTerms (el plan de la tabla).

Tengo algunos ejemplos más concretos de la asignación de sintaxis si se requiere, pero es probablemente la mejor manera de trabajar con su propio modelo y no tengo suficiente información sobre las tablas de base de datos para proporcionar ejemplos concretos.

No sé si esto es posiblemente debido a mi NHibernate la experiencia es limitada, pero podría crear un BaseDetail clase que tiene sólo de las propiedades de los Detalles a medida que se asignan directamente a la tabla de Detalle.

A continuación, crear una segunda clase que hereda de la BaseDetail que tiene la clase adicional de los Padres objeto del Plan, así usted puede crear un BaseDetail clase cuando se desea crear una fila de Detalle y asignar el PlanId, pero si usted necesita para llenar un completo registro de Detalle con el Padre del plan de objeto se puede utilizar el heredado Detalle de la clase.

No sé si eso hace un montón de sentido, pero hágamelo saber y voy a aclarar.

Creo que el problema que tenemos aquí es que su AcceptedOffer objeto contiene un Plan de objeto y, a continuación, su Plan de objeto parece contener una AcceptedOffers colección que contiene AcceptedOffer objetos.Lo mismo con los Clientes.El hecho de que los objetos son de un niño de unos a otros es lo que causa el problema, creo.

Del mismo modo, lo que hace que su AcceptedOffer complejo tiene dos responsabilidades:indica ofertas incluidas en un plan, indica la aceptación por parte del cliente.Que viola el Principio de Responsabilidad Único.

Puede que tenga que diferenciar entre una Oferta que está bajo un Plan, y una Oferta que es aceptado por los clientes.Así que aquí es lo que voy a hacer:

  1. Crear una Oferta de objetos que no tienen un estado, por ejemplo, no tiene un cliente y no tiene un estado-sólo tiene un OfferId y el Plan pertenece como sus atributos.
  2. Modificar su Plan de objeto Ofrece una colección (que no tiene que haber aceptado la oferta en su contexto).
  3. Por último, modificar su AcceptedOffer objeto, de forma que contiene una Oferta, el Cliente, y un Estado.El cliente sigue siendo el mismo.

Creo que esto será suficiente para desenredar sus asignaciones de NHibernate y objeto de ahorrar problemas.:)

Un consejo que puede (o no) ser útil en NHibernate:puede asignar los objetos contra los puntos de vista, como si la Vista era una tabla.Sólo tiene que especificar el nombre de la vista como un nombre de tabla;mientras todos NO NULOS campos se incluyen en la vista y la asignación funcionará bien.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top