Le associazioni unidirezionali portano a campi di chiave esterna non richiesti tramite NHibernate

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

Domanda

Aggiorna Aggiunte mappature di seguito

Riepilogo domande Ho un database con molti campi di chiave esterna richiesti e una base di codice con molte associazioni unidirezionali. Voglio usare NHibernate, ma per quanto ne so, devo rendere NULLable i campi della chiave esterna nel database (non un'opzione realistica) o cambiare le associazioni in bidirezionali (neanche l'ideale). Altre opzioni che ho perso?

Fondo Ho aderito a un progetto che utilizza NHibernate per mappare le tabelle 1: 1 al cosiddetto "tecnico" oggetti. Dopo il recupero dei dati, gli oggetti vengono mappati sul modello di dominio effettivo (stile AutoMapper, implementato in modo diverso). So che si tratta di un passaggio non necessario e desidero proporre di rimuoverlo dal team. Tuttavia, sto riscontrando un problema.

Il modello di dominio contiene molte associazioni unidirezionali: l'oggetto Case ha un elenco di Persone associate al caso, ma le Persone non hanno un riferimento all'oggetto Case. Nello schema del database sottostante, la tabella Persona ha un campo chiave esterna obbligatorio che fa riferimento all'ID caso. Il modello di dati:

[ERD]
               PERSON
CASE           Id*            Ids are generated by the DB
Id*    <--FK-- CaseId*        * denotes required fields
(other)        (other)         

Il modello di dominio è simile al seguente:

public class Person : DomainEntity
{ // DomainEntity implements Id. Non-essential members left out }

public class Case : DomainEntity
{
  public virtual IList<Person> Persons { get; set; }
}

La chiamata a session.Save () su un caso porta a un errore del database (CaseId richiesto durante l'inserimento nella persona), poiché NHibernate inizia con l'inserimento delle voci persona, seguito dalla voce caso e termina aggiornando la colonna CaseId nella persona inserimenti. Se la colonna CaseId nel database viene modificata in non richiesta (consenti NULL), tutto funziona come dovrebbe ... tuttavia, al momento tale modifica non è un'opzione (il modello di database è condiviso da più app per almeno un'altra anno). L'unico modo in cui ho trovato NHibernate per eseguire correttamente le azioni del database è cambiando l'associazione in bidirezionale, ovvero cambiando Persona in

public class Person : DomainEntity
{ 
  public virtual Case Case { get; set; }
}

Ciò comporterebbe tuttavia modifiche significative alla base di codice esistente, quindi preferirei delle alternative, se presenti. Ho giocato con le mappature dei componenti, ma non va bene dato che la maggior parte delle associazioni nel nostro modello non sono composizioni (UML) reali. Ci sono altre opzioni che mi sono perso? TIA!

Modifica La mappatura (fluente) di Case appare così:

public class CaseMapping : ClassMap<Case>
{
    public CaseMapping()
    {
        Not.LazyLoad();

        Id(c => c.Id).GeneratedBy.Identity();
        Map(x => x.Code).Not.Nullable().Length(20);
        Map(x => x.Name).Not.Nullable().Length(100);
        HasMany<Person>(x => x.Persons)
            .AsBag()
            .KeyColumn("CaseId")
            .ForeignKeyConstraintName("FK_Person_Case")
            .Cascade.AllDeleteOrphan();
    }
}

Se uso SessionSource.BuildSchema per un database di test, questo genera una tabella Person con una colonna CaseId nullable. Non ho trovato il modo per farlo funzionare con un campo CaseId non annullabile senza associazioni bidirezionali. Le istruzioni SQL (pseudo) eseguite:

  1. INSERISCI IN Caso ...
  2. seleziona @@ identità
  3. INSERISCI IN Person / * (tutte le colonne tranne CaseId) * /
  4. seleziona @@ identità
  5. AGGIORNA Persona SET CaseId =? WHERE Id =?; @ P0 = 2, @ p1 = 1
È stato utile?

Soluzione

Penso che potresti essere sfortunato qui. I documenti su http://nhibernate.info/doc/nh/en /index.html#collections-onetomany stato:

Se la colonna di un'associazione è dichiarata NOT NULL, NHibernate può causare violazioni dei vincoli quando crea o aggiorna l'associazione. Per evitare questo problema, è necessario utilizzare un'associazione bidirezionale con l'estremità più apprezzata (il set o il sacchetto) contrassegnata come inversa = " true "

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top