Programmazione delle interfacce durante la mapping con Fluent NHibernate

Sono stato sottoposto alla sottomissione e ho iniziato a studiare Fluent NHibernate (nessuna esperienza precedente su NHibernate). Nel mio progetto, sto programmando le interfacce per ridurre l’accoppiamento ecc. Ciò significa che praticamente “tutto” si riferisce all’interfaccia anziché al tipo concreto (IMessage anziché Message). Il pensiero dietro questo è quello di rendere più verificabile la possibilità di prendere in giro le dipendenze.

Tuttavia, (Fluente) NHibernate non lo adora quando cerco di mappare interfacce anziché classi concrete. Il problema è semplice: secondo Fluent Wiki, è intelligente definire il campo ID della mia class, ad esempio

int Id { get; private set; } 

per ottenere una tipica chiave primaria generata automaticamente. Tuttavia, questo funziona solo con classi concrete – Non posso specificare un livello di accesso su un’interfaccia, dove deve essere la stessa linea

 int Id { get; set; } 

e immagino che neghi di rendere il setter privato nella class concreta (l’idea è che solo NHibernate dovrebbe mai impostare l’ID come assegnato dal DB).

Per ora, immagino che renderò pubblico il setter e cercherò di evitare la tentazione di scrivere su di esso .. Ma qualcuno ha un’idea di quale sarebbe il modo “corretto”, best practice per creare una chiave primaria appropriata campo a cui solo NHibernate può scrivere mentre sta ancora programmando le interfacce?

    AGGIORNATO

    Da quanto ho capito dopo le due risposte di Mookid e James Gregory, potrei essere sulla strada sbagliata – non ci dovrebbe essere una ragione per me per avere un’interfaccia per quadro come ora. Va tutto bene. Immagino che la mia domanda diventi allora – non c’è motivo di programmare il 100% contro un’interfaccia per qualsiasi quadro? E se c’è anche una singola situazione in cui ciò potrebbe essere giustificato, è ansible farlo con (Fluente) NHibernate?

    Lo chiedo perché non lo so, non per essere critico. Grazie per le risposte. 🙂

    AGGIORNAMENTO: l’ uso della sottoclass union non è supportato tramite l’interfaccia fluente-niberneno fornisce. Dovrai utilizzare un normale file di mapping hbm e aggiungerlo.

    Anch’io sto provando a farlo con fluente NHibernate. Non penso che dovrebbe essere un problema nel mappare le interfacce. Si desidera utilizzare una strategia di ereditarietà, in particolare la strategia della tabella per la class concreta .

    In sostanza, si crea una definizione di mapping per la class base (in questo caso la propria interfaccia) e si specifica come NHibernate dovrebbe trattare con gli implementatori usando la sottoclass union.

    Quindi, per esempio, questo dovrebbe permetterti di creare associazioni polimorfiche:

               ...  

    Nota come l’Id è lo stesso per tutti gli implementatori concreti. NHibernate ha richiesto questo. Inoltre, la tabella IAccountManager non esiste realmente.

    Puoi anche provare a sfruttare il Polymorphism implicito di NHibernate (documentato sotto la strategia della tabella per la class concreta), ma ha un sacco di limitazioni.

    Mi rendo conto che si tratta di una diversione, e non di una risposta alla tua domanda (anche se penso che il mookid lo abbia coperto).

    Dovresti davvero valutare se le interfacce sulle tue entity framework di dominio forniscono effettivamente qualcosa di valore; è raro trovare una situazione in cui devi effettivamente farlo.

    Ad esempio: in che modo affidarsi a IMessage meno accoppiato che affidarsi a Message , quando entrambi (quasi) condividono senza dubbio firme identiche? Non dovresti aver bisogno di prendere in giro un’ quadro, perché è raro che abbia abbastanza comportamenti da richiedere la derisione.

    Puoi regolare la tua interfaccia per contenere solo un getter:

     public interface ISomeEntity { int Id { get; } } 

    La tua class concreta può ancora implementare un setter, e dal momento che stai programmando sulle tue interfacce non chiamerai mai il setter “per sbaglio”.

    Se non vuoi impostare l’id anche se tieni un riferimento a un’istanza concreta, puoi astenersi dall’implementare un setter e quindi consentire a NHibernate di accedere al campo anziché alla proprietà – è vero, NHibernate può utilizzare alcuni trucchetti di riflessione nifty per imposta il tuo campo id direttamente anziché richiamare la proprietà. Quindi potresti mappare l’id in questo modo:

     Id(e => e.Id).Access.AsCamelCaseField(); 

    nel qual caso la tua proprietà Id deve essere supportata da un campo id corrispondente. Esistono più convenzioni di denominazione, ad esempio se preferisci i trattini bassi come prefisso del campo privato.

    Sto avendo esattamente lo stesso problema. Sfortunatamente ho una ragione valida per usare le interfacce di entity framework; il modello di quadro verrà implementato in modi diversi e con mappature diverse per cliente.

    L’intero modello deve essere di sola lettura, quindi le interfacce sono dello stile:

     public interface IAccount { long AccountId { get; } IHouse House { get; } } public interface IHouse { long HouseId { get; } HouseStatus Status { get; } IList Accounts { get; } } 

    Implementazioni concrete implementano quindi questi con i setter interni:

     public class Account: IAccount { public virtual long AccountId { get; internal set; } public virtual IHouse House { get; internal set; } } public class House: IHouse { public virtual long HouseId { get; internal set; } public virtual HouseStatus Status { get; internal set; } public virtual IList Accounts { get; internal set; } } 

    Ho seguito la rotta della mapping verso le classi concrete. Tutto va bene fino a quando non crei relazioni che restituiscono interfacce e devono essere lanciate su implementazioni concrete.

     HasMany(x => x.Accounts) 

    può diventare

     HasMany(x => x.Accounts) 

    Ma non esiste un “cast” equivalente

     References(x => x.House) 

    La mapping alle interfacce (la soluzione più netta) solleva il problema sopra menzionato in quanto l’Id deve esistere sulla class più alta per l’impostazione e richiede un setter sull’interfaccia.

     public sealed class AccountMap : ClassMap { public PokerPlayerMap() { Id(x => x.AccountId, "account_id"); DiscriminateSubClassesOnColumn("Type").SubClass(s => { References(x => x.House); }); } } 

    Per ora, la mia unica soluzione è aggiungere setter a tutti i campi ID dell’interfaccia. È un peccato che l’Id non possa esistere all’interno di una sottoclass o che il suo tipo sia lanciato dall’interfaccia.

    Sembra che non abbia abbastanza reputazione per commentare le risposte di altre persone, in quanto tale, dovrò farne una risposta a pieno titolo.

    I riferimenti ora hanno un sovraccarico generico per consentire il cast che il Gecko stava cercando nella sua risposta.