Ho creato una convenzione EF che imposta un nome schema per una classe basata sull'interfaccia che implementa direttamente o indirettamente.
public class TableNameConvention<T> : IStoreModelConvention<EntitySet>
{
private readonly string SchemaName;
public TableNameConvention(string schemaName)
{
this.SchemaName = schemaName;
}
public virtual void Apply(EntitySet entitySet, DbModel model)
{
// Get the name of the Entity
string name = entitySet.Name;
// Check TEntityType Assembly for entitySet type
Type type = typeof(T).Assembly.GetTypes().Where(x => x.Name == name).SingleOrDefault();
// Check if type was found
if (type != null)
{
// Check if type implements Type Parameter and if so, set schema
if (typeof(T).IsAssignableFrom(type)) entitySet.Schema = SchemaName;
}
entitySet.Table = FormatName(name);
}
Questo funziona bene il 95% del tempo. Tuttavia, se esiste un'altra classe con lo stesso nome in qualsiasi punto dell'Assembly, verrà restituito il valore predefinito. Posso cambiarlo in FirstOrDefault, ma non c'è ancora garanzia che il primo sia quello che sto effettivamente cercando.
So che senza il nome completo, non sarà mai al 100%, ma qualcuno ha qualche suggerimento per migliorare le possibilità di ottenere il tipo giusto?
AGGIORNARE
Ho cambiato il seguente:
Type type = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(t => t.GetTypes())
.Where(t => t.IsClass && t.Namespace == typeof(T).Namespace)
.FirstOrDefault(t => t.Name.Equals(name));
Funzionerà solo se la classe derivata si trova nello stesso spazio dei nomi della classe base, comunque. Quindi se qualcuno ha altri suggerimenti, per favore aiutatemi!
La risposta breve è che non esiste un modo per ottenere il Type
effettivo dell'entità direttamente da un EntitySet
EF, almeno non nel modello di archiviazione.
Per far funzionare il codice sopra, ho aggiornato la classe come segue:
private readonly string SchemaName;
private readonly string Namespace;
public TableNameConvention(string schemaName, string @namespace)
{
this.SchemaName = schemaName;
this.Namespace = @namespace;
}
e quindi aggiornato dove metodo sulla query Linq per ottenere il tipo dall'AppDomain
Type type = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(t => t.GetTypes())
.Where(t => t.IsClass && t.Namespace == this.Namespace)
.FirstOrDefault(t => t.Name.Equals(name));
Funzionerebbe?
// Check TEntityType Assembly for entitySet type
Type type = typeof(T).Assembly.GetTypes().Where(x => x == entitySet.GetType()).SingleOrDefault();