2012-12-20 18 views
11

Devo usare il tipo "datetime2" di Sql Server su tutti i DateTime e DateTime? proprietà di tutti i miei oggetti entità. Questo avviene normalmente con l'API fluente in questo modo:Un Entity Framework più intelligente Codefirst API fluente

modelBuilder.Entity<Mail>().Property(c => c.SendTime).HasColumnType("datetime2"); 

Tuttavia, preferirei non farlo manualmente per ogni campo DateTime in ogni tipo di entità. (Non ho un tipo di base comune in cui tutte le proprietà DateTime possono essere posizionate, perché le proprietà DateTime sono specifiche per i tipi di entità in cui sono definite).

La breve domanda: quali sono le mie opzioni?

La lunga domanda: mi stava prendendo in considerazione utilizzando la riflessione e fatto un atttempt, ma ha ottenuto molto disordinato come è sembra l'API fluente non è realmente adatto per questo tipo di lavoro perché ho dovuto chiamare i metodi API fluente generici via riflessione. Qui è il mio tentativo disordinato:

protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
     var genericEntityMethod = modelBuilder.GetType().GetMethod("Entity"); 
     var entityTypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsClass && !t.IsAbstract && t.GetInterface("IEntity") != null); 
     foreach (var t in entityTypes) { 
      var props = t.GetProperties().Where(p => 
       p.GetSetMethod() != null && 
       p.GetGetMethod() != null && 
       (p.PropertyType == typeof (DateTime) || 
       p.PropertyType == typeof(DateTime?))); 
      foreach (var propertyInfo in props) { 
       var entityMethod = genericEntityMethod.MakeGenericMethod(t.GetType()); 
       var entityTypeConfiguration = entityMethod.Invoke(modelBuilder,null); 
       var lambdaExpression = Expression.Lambda(Expression.MakeMemberAccess(Expression.Parameter(t), propertyInfo), Expression.Parameter(t)); 

       //var propertyMethod = entityTypeConfiguration.GetType().GetMethod("Property"); // Cant get this to work 
       var propertyMethods = entityTypeConfiguration.GetType().GetMethods().Where(m => m.ReturnType == typeof(DateTimePropertyConfiguration)).ToList(); 
       var propertyMethod = propertyInfo.PropertyType == typeof (DateTime) ? propertyMethods[0] : propertyMethods[1]; 

       var dateTimePropertyConfiguration = propertyMethod.Invoke(entityTypeConfiguration, new object[] {lambdaExpression}); 
       var hasColumnTypeMethod = entityTypeConfiguration.GetType().GetMethod("HasColumnType"); 
       hasColumnTypeMethod.Invoke(dateTimePropertyConfiguration, new object[]{ "datetime2" }); 
      } 
     } 
     base.OnModelCreating(modelBuilder); 
    } 

Questo non riesce in questa linea:

    var dateTimePropertyConfiguration = propertyMethod.Invoke(entityTypeConfiguration, new object[] {lambdaExpression}); 

con questo errore (Entities.Order è uno dei miei oggetti entità che hanno una proprietà DateTime):

Object of type 'System.Linq.Expressions.Expression`1[System.Func`2[Entities.Order,System.Nullable`1[System.DateTime]]]' cannot be converted to type 'System.Linq.Expressions.Expression`1[System.Func`2[System.RuntimeType,System.Nullable`1[System.DateTime]]] 

Qualcuno può aiutarmi con questo approccio di riflessione o meglio, mostrarmi un modo più semplice per evitare di dover scrivere manualmente un sacco di cose di API fluente?

risposta

4

C'è l'approccio molto meglio. Sfortunatamente l'approccio è basato su convenzioni personalizzate che saranno disponibili in EF6. Puoi provare con lo EF6 Alpha 2 e giocare con le convenzioni personalizzate - lo walkthrough contiene un esempio con i tuoi esatti requisiti.

Per risolvere il problema con la riflessione, controllare questo blog article. Descrive il codice per la generazione di mapping con riflessione (dovrebbe essere correlato open source project).

Problemi correlati