2012-03-23 2 views
0

Est-il possible dans Entity Framework de créer une méthode de conversion personnalisée pour convertir un entier en une entité via une conversion explicite? J'ai fait des recherches à ce sujet, et je ne sais pas par où commencer.Conversion explicite d'entier en entité?

Voici un exemple de ce que j'essaie de faire.

int activeTeacherId = 38; 
Teacher activeTeacher = (Teacher)activeTeacherId; 

Modifier 1 Après quelques recherches rapides, je me suis dit que je dois sans doute faire quelque chose avec le EntityObject si je dois tout faire pour être vraiment générique et flexible. Cependant, je ne sais pas comment.

Éditer 2 De ma propre expérience, j'ai réussi à créer le code suivant. Cependant, pour des raisons évidentes, je ne peux pas obtenir ceci dans un contexte statique. Si je pouvais juste obtenir le type de l'objet dans lequel il est converti (puisqu'il n'est pas toujours converti en EntityObject, mais parfois en Person ou en Teacher), cela fonctionnerait théoriquement.

public class EntityObject : System.Data.Objects.DataClasses.EntityObject 
{ 
    public static explicit operator EntityObject(int id) 
    { 
     var container = ModelContainer.Instance; 

     var thisType = this.GetType(); //this can't be done from a static context, so how do we retrieve the type that we are converting into? 
     var containerType = typeof (ModelContainer); 

     dynamic setProperty = typeof (ModelContainer).GetProperty(thisType.Name + "Set"); 

     ObjectSet<dynamic> set = setProperty.GetValue(container); 

     return set.FirstOrDefault(o => o.Id == id); 
    } 
} 
+1

Le faites-vous contre CoreFirst ou ModelFirst? –

+0

Modèle-première conception :) –

+0

n'est-ce pas juste une propriété de navigation? –

Répondre

0

Je l'ai enfin fait! Basé sur les suggestions de Peter (voir son commentaire sur ma question), j'ai créé une méthode d'extension sur "int" qui me permet d'effectuer les actions que je cherche.

Je suis assez fier de cet algorithme puisque j'en ai compris la plupart moi-même. Cela implique une réflexion sérieuse, une création dynamique d'expressions lambda et leur évaluation. Mais ça marche!

Des suggestions pour le rendre plus court ou mieux seraient appréciées.

public static class EntityObjectExtensions 
{ 

    private static int Id; 

    public static T ToEntity<T>(this int id) where T : class 
    { 

     lock(typeof(ModelContainer)) 
     { 

      Id = id; 

      var container = ModelContainer.Instance; 

      var thisType = typeof (T); 
      while (thisType.BaseType != typeof (EntityObject)) 
      { 
       thisType = thisType.BaseType; 
      } 

      var setProperty = typeof (ModelContainer).GetProperty(thisType.Name + "Set"); 

      dynamic set = setProperty.GetValue(container); 

      var firstOrDefaultMethod = 
       typeof (Enumerable).GetMethods().FirstOrDefault(m => m.Name == "FirstOrDefault" && m.GetParameters().Count() == 2); 
      var firstOrDefaultGenericMethod = firstOrDefaultMethod.MakeGenericMethod(thisType); 

      var lambda = typeof (Func<,>); 
      var genericLambda = lambda.MakeGenericType(thisType, typeof (bool)); 

      var lambdaParameter = (Func<T, bool>) Delegate.CreateDelegate(genericLambda, typeof(EntityObjectExtensions).GetMethod("Compare", BindingFlags.Static | BindingFlags.NonPublic)); 

      dynamic item = firstOrDefaultGenericMethod.Invoke(null, new object[] {set, lambdaParameter}); 

      return (T) item; 

     } 

    } 

    private static bool Compare(dynamic item) 
    { 

     lock (typeof(ModelContainer)) 
     { 

      return item.Id == Id; 

     } 
    } 

} 
+0

Félicitations! Je me demande encore pourquoi la simple récupération d'une entité par Id à partir de la collection dans le contexte n'est pas appropriée pour vous. Vous devez spécifier le type, donc vous savez déjà que vous cherchez un 'Teacher' par id 38. Alors pourquoi ne pas faire' context.Teachers.FirstOrDefault() '? Oui, c'est plus long que 38.ToEntity (), mais probablement beaucoup plus rapide (pas de réflexion, dynamique) et clair comme la lumière du jour. De plus, vous avez besoin de ModelContainer.Instance, vous êtes donc bloqué avec un modèle de cycle de vie de contexte. –

Questions connexes