2012-02-17 3 views
4

Voici un projet simple basé sur une classe Poco nommée Task:Include dérivé propriété dans une requête LINQ to entité

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (MyDbContext ctx = new MyDbContext()) 
     { 
      // first query 
      DateTime compareDate = DateTime.Now + TimeSpan.FromDays(3); 
      var res = ctx.Tasks.Where(t => t.LastUpdate < compareDate).ToList(); 

      // second query 
      res = ctx.Tasks.Where(t => t.ShouldUpdate).ToList(); 
     } 
    } 
} 

public class MyDbContext : DbContext 
{ 
    public DbSet<Task> Tasks { get; set; } 
} 

public class Task 
{ 
    public int ID { get; set; } 
    public DateTime LastUpdate { get; set; } 
    public bool ShouldUpdate 
    { 
     get 
     { 
      return LastUpdate < DateTime.Now + TimeSpan.FromDays(3); 
     } 
    } 
} 

Ce que je veux faire est d'interroger le contexte dbset y compris dans la clause where de la ShouldUpdate propriété dérivée.

La "première requête fonctionne bien" (je ne peux pas l'écrire sur une seule ligne mais cela n'a pas d'importance).

Comme vous le savez, nous obtenons un NotSupportedException sur la "deuxième requête", avec le message suivant: Le membre de type spécifié 'ShouldUpdate' n'est pas pris en charge dans LINQ to Entities. Seuls les initialiseurs, les membres d'entité et les propriétés de navigation d'entité sont pris en charge. C'est exact et je peux comprendre pourquoi cela se produit, mais j'ai besoin d'encapsuler les informations dérivées dans l'objet Task afin que je puisse afficher la propriété dans une grille ou l'utiliser dans tous les autres endroits, sans dupliquer la logique derrière elle.

Existe-t-il une technique intelligente pour ce faire? NB: Comment s'appelle la propriété ShouldUplate? dérivé? calculé? calculé?

Répondre

3

Enfin j'ai trouvé la solution .. Vous pouvez stocker les requêtes partielles (Expressions) dans fileds statiques et de les utiliser comme ceci:

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (MyDbContext ctx = new MyDbContext()) 
     { 
      res = ctx.Tasks.Where(Task.ShouldUpdateExpression).ToList(); 
     } 
    } 
} 

public class MyDbContext : DbContext 
{ 
    public DbSet<Task> Tasks { get; set; } 
} 

public class Task 
{ 
    public int ID { get; set; } 
    public DateTime LastUpdate { get; set; } 
    public bool ShouldUpdate 
    { 
     get 
     { 
      return ShouldUpdateExpression.Compile()(this); 
     } 
    } 

    public static Expression<Func<Task, bool>> ShouldUpdateExpression 
    { 
     get 
     { 
      return t => t.LastUpdate < EntityFunctions.AddDays(DateTime.Now, 3); 
     } 
    } 
} 
+0

J'ai un problème similaire, mais je reçois une erreur "non supporté" même lorsque j'essaie d'utiliser une expression statique comme ci-dessus. Une idée de pourquoi cela pourrait être? – MysteriousWhisper

+0

pouvez-vous donner un exemple? –

0

Vous devez placer la logique ShouldUpdate dans la requête linq-to-enitites. Vous pouvez utiliser EntityFunctions.AddDays pour vous aider comme si

res = ctx.Tasks.Where(t => t.LastUpdate < EntityFunctions.AddDays(DateTime.Now, 3)).ToList(); 
1

modèle de référentiel fournirait une meilleure abstraction dans ce cas. Vous pouvez centraliser la logique comme suit. Définissez une nouvelle propriété TaskSource dans votre contexte.

public class MyDbContext : DbContext 
{ 
    public DbSet<Task> Tasks { get; set; } 

    public IQueryable<Task> TaskSource 
    { 
     get 
     { 
      return Tasks.Where(t => t.LastUpdate < EntityFunctions.AddDays(DateTime.Now, 3)); 
     } 
    } 
} 
+0

si .. vous dites que le modèle de données objets shouldn n'incluez aucune logique du tout? –

+0

@ Les entités user846168 peuvent contenir une logique. L'endroit approprié pour mettre ce type de logique dépend du contexte. – Eranga

Questions connexes