2009-06-15 41 views
5

Estoy trabajando con una base de datos heredada que usa claves compuestas. Y estoy tratando de usar NHibernate para insertar un nuevo registro en la base de datos. NHibernate especifica que tengo que crear el ello de forma manual, pero cuando intento insertar con este id me sale el mensaje:Insertar un registro con una clave compuesta con NHibernate

System.Data.SqlClient.SqlException: Cannot insert explicit value for identity column in table 'tablename' when IDENTITY_INSERT is set to OFF. 

no puedo tocar cualquiera de los ajustes db, ya que son administrados por la oficina central en EE.UU..

I encontraron que pueda hacer un inserto db a través de:

insert into tablename (tablename_country_id, /*extra fields here*/) values (16, /*extra values here*/) 

y la columna de la tablename_id se incrementa automáticamente.

Es posible escribir algún tipo de controlador que me permita crear un objeto ID con el conjunto CountryId y hacer que aumente automáticamente la propiedad Id.

Saludos.


Código Ejemplo:

Tabla Definición:

CREATE TABLE [dbo].[tablename](
    [tablename_country_id] [int] NOT NULL, 
    [tablename_id] [int] IDENTITY(1,1) NOT NULL, 

    -- more fields here 

    CONSTRAINT [pk_tablename] PRIMARY KEY 
    (
     [tablename_country_id] ASC, 
     [tablename_id] ASC 
    ) 
) 

archivos de clase:

public class ModelObject 
{ 
    public ID { get; set; } 
    // more properties here 
} 

public class ID : INHibernateProxy 
{ 
    public int Id { get; set; } 
    public int CountryId { get; set; } 
    public ILazyInitializer HibernateLazyInitializer { get { throw new ApplicationException(); } } 
} 

Archivo de asignación:

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Model" assembly="API"> 
    <class name="ModelObject" table="dbname.dbo.tablename" lazy="false"> 
     <composite-id name="Id" class="ID"> 
      <key-property name="Id" column="tablename_id" type="int" /> 
      <key-property name="CountryId" column="tablename_country_id" type="int" /> 
     </composite-id> 
     <!-- more properties here --> 
    </class> 
</hibernate-mapping> 

Respuesta

0

Creo que puede establecer una columna de identidad para una de sus claves en la clave compuesta.

Yo sé que en fluentnhibernate tengo un nombre de columna de identidad para un omposite clave

+0

¿Cómo afectaría esto al almacenamiento en caché de objetos? En particular, la 'sesión. Obtiene (id);' con la posibilidad de duplicados en la columna 'tablename_id'. – zonkflut

+0

esta opción arroja una FKUnmatchingColumnsException 'debe tener el mismo número de columnas que la clave primaria referenciada' – zonkflut

0

tal vez esto puede funcionar. Si agrega la declaración de actualización explícitamente, también, si necesita cambiarla a una sProc o algo así, puede hacerlo.

https://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/querysql.html#querysql-cud 

aquí hay un ejemplo del concepto sproc.

<class name="Person"> 
    <id name="id"> 
     <generator class="increment"/> 
    </id> 
    <property name="name" not-null="true"/> 
    <sql-insert>exec createPerson ?, ?</sql-insert> 
    <sql-delete>exec deletePerson ?</sql-delete> 
    <sql-update>exec updatePerson ?, ?</sql-update> 
</class> 
0

entiendo que no se puede modificar la tabla de base de datos o limitaciones, pero son absolutamente seguro de que los objetos de la base realmente entender que usted tiene que utilizar una clave compuesta NHibernate?

Se debe utilizar una clave compuesta NHibernate para aquellas tablas en las que la singularidad de una fila está determinada por más de una columna. En el ejemplo que proporcionó, resulta que la singularidad de cada fila en realidad solo está determinada por la columna single tablename_id. La clave primaria resulta ser superflua: es decir, no se puede violar porque uno de sus elementos constituyentes es una columna de identidad que siempre será diferente.

Quizás la clave primaria haya sido colocada allí por sus colegas por algún otro motivo (indexación, etc.).

Esto significa que su mapeo NHibernate realmente debería colapsar a algo bastante simple: un POCO normal con una sola asignación de ID a nombre_tabla_id utilizando un generador de identificador nativo NHibernate simple. La propiedad CountryID luego une sus propiedades elípticas como una propiedad normal para lograr su objetivo: CountryID se configura con ID auto-incrementado por la base de datos.

public class ModelObject 
{ 
    public int ID { get; set; } 
    public int CountryID { get; set; } 
    // more properties here 
} 

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Model" assembly="API"> 
    <class name="ModelObject" table="dbname.dbo.tablename" lazy="false"> 
     <id name="ID" column="tablename_id" type="int"> 
     <generator class="native" /> 
    </id> 
     <property name="CountryID" column="tablename_country_id" type="int" /> 
     <!-- more properties here --> 
    </class> 
</hibernate-mapping> 
+0

se necesita el CountryID ya que se usa para identificar de manera única qué instancia de la base de datos (es decir, qué país) está en replicación. Esta fue la solución original elegida para tratar con bases de datos distribuidas. Por lo tanto, para seguir siendo correcto, tengo que usar la clave compuesta :( – zonkflut

Cuestiones relacionadas