NHibernate applica fluentemente Not Nullable sul riferimento a chiave esterna
-
22-09-2019 - |
Domanda
Mi stavo solo bagnando i piedi con alcune convenzioni di Fluent NHibernate AutoMap e mi sono imbattuto in qualcosa che non riuscivo a capire.Presumo che non sto cercando nel posto giusto...Fondamentalmente cercando di imporre NOT-NULL sul lato "molti" della relazione uno a molti.Sembra che, utilizzando l'automapping, la proprietà genitore Id sia sempre nullable nel database.
Ho fatto qualche ricerca su StackOverFlow e ho trovato domande simili, ma nulla relativo ad AutoMapping e Convenzioni (a meno che non me ne sia accorto).
Esempio veloce...
public class Group // One Group
{
public Group() { this.Jobs = new List<Job>(); }
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual IList<Job> Jobs { get; protected set; }
}
public class Job // Has many Jobs
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
// Trying to make this field not-nullable in the database.
public virtual Group Group { get; set; }
}
Pensavo che avrei potuto creare una convention come...
public class OneToManyConvention : IHasOneConvention
{
public void Apply(IOneToOneInstance instance)
{
// Nullable() isn't a valid method...
instance.Not.Nullable();
}
}
Ma sembra che IOneToOnInstance non abbia un metodo Nullable().Posso farlo se creo un file di mappa per Job, ma cercando di evitare qualsiasi file di mappa e attenermi alla mappatura automatica.
Mi sono imbattuto in questo collegamento nell'elenco dei gruppi Fluent descrivendo qualcosa di simile.
Che descrive qualcosa del genere...
public class NotNullPropertyConvention : IPropertyConvention
{
public bool Accept(IProperty target)
{
return true;
}
public void Apply(IProperty target)
{
target.Not.Nullable();
}
}
Ma ciò solleva le domande di...1) Come determinare che IProperty sia un lavoro (o qualsiasi proprietà figlio che sia un collegamento al genitore)
2) In quella pagina è stato menzionato che l'utilizzo di questo avrebbe sovrascritto le mie sostituzioni manuali, ad es.se un collegamento a una proprietà molto specifica doveva essere NULL.Quale sarebbe un problema (se è ancora un problema, ma non è possibile eseguire il test senza prima capire il punto 1)
Qualche idea su questo?Mi sto perdendo qualcosa?
Aggiornamento 1
Ancora niente da fare.Anche quanto segue non impone ancora Not-Nullable nello schema del database...
public class FluentConvention : IPropertyConvention
{
public void Apply(IPropertyInstance instance)
{
instance.Not.Nullable();
}
}
Lo stesso vale per tutti gli altri campi...
/alzata di spalle
Qualche idea?
Aggiornamento 2
Anche se questa non è la risposta che stavo cercando, ho trovato una soluzione...Stavo utilizzando l'assembly NHibernate Validator e all'interno di quell'assembly c'è un attributo [NotNull].Se decorassi la mia classe con l'attributo Validator e associassi ValidationEngine a NHibernate prima della creazione dello schema, contrassegnerebbe la colonna del database FK come Not-Nullable.
public class Job // Has many Jobs
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
[NHibernate.Validator.Constraints.NotNull]
public virtual Group Group { get; set; }
}
Se qualcuno ha bisogno del codice completo per l'inizializzazione di NHibernate + ValidationEngine, fatemelo sapere.Sto ancora cercando un modo per farlo utilizzando il percorso della pura convenzione di mappatura, se qualcuno ha qualche informazione...
Grazie!
Soluzione
Puoi sovrascrivere le proprietà mappate automaticamente come parte della tua AutoMap in Fluenttly.Configure().
Quindi puoi fare questo:
.Override<Job>(map => map.References(x => x.Group).Not.Nullable())
Tuttavia non è esattamente conveniente se hai molte classi che ne hanno bisogno.
Modificare: Puoi anche specificare l'override in una classe che implementa IAutoMappingOverride in questo modo:
public class JobMappingOverride : IAutoMappingOverride<Job>
{
public void Override(AutoMapping<Job> mapping)
{
mapping.References(x => x.Group).Not.Nullable();
}
}
e includerlo in questo modo:
.UseOverridesFromAssemblyOf<JobMappingOverride>()
Ciò manterrebbe la tua configurazione fluida un po' più pulita.
Altri suggerimenti
Sembra che IPropertyConvention
viene chiamato solo su proprietà semplici delle tue classi.Se la tua proprietà fa riferimento a un'altra classe, devi utilizzare IReferenceConvention
pure.
Prova questo:
public class FluentConvention : IPropertyConvention, IReferenceConvention
{
public void Apply(IPropertyInstance instance)
{
instance.Not.Nullable();
}
public void Apply(IManyToOneInstance instance)
{
instance.Not.Nullable();
}
}