2012-01-19 16 views
6

Ho creato un'interfaccia implementata dalla classe DbContext, questo mi consente di creare un contesto db falso per il test dell'unità. Questo funziona bene per tutto il mio LINQ interroga finora, ma uno, dove ottengo la seguente eccezione:DbContext genera un'eccezione nella query quando si accede tramite l'interfaccia

Unable to create a constant value of type 'DemoApp.Member'. Only primitive types ('such as Int32, String, and Guid') are supported in this context. 

L'esecuzione della query LINQ attraverso l'interfaccia genera l'eccezione di cui sopra, tuttavia quando si esegue la stessa query direttamente sul mio DbContext la query funziona al 100%. Ecco l'interfaccia e relative definizioni di codice demo:

interface IDemoContext : IDisposable 
{ 
    IDbSet<Member> Members { get; set; } 
    IDbSet<Team> Teams { get; set; } 
} 

public partial class DemoContext : DbContext, IDemoContext 
{ 
    public DemoContext() : base("name=DemoContext"){} 

    public IDbSet<Member> Members { get; set; } 
    public IDbSet<Team> Teams { get; set; } 
} 

public partial class Member 
{ 
    public Member() 
    { 
     this.SecondaryTeams = new HashSet<Team>(); 
    } 

    public int ID { get; set; } 
    public string Name { get; set; } 
    public int? PrimaryTeamID { get; set; } 

    public virtual Team PrimaryTeam { get; set; } 
    public virtual ICollection<Team> SecondaryTeams { get; set; } 
} 

public partial class Team 
{ 
    public Team() 
    { 
     this.PrimaryMembers = new HashSet<Member>(); 
     this.SecondaryMembers = new HashSet<Member>(); 
    } 

    public int ID { get; set; } 
    public string Name { get; set; } 

    public virtual ICollection<Member> PrimaryMembers { get; set; } 
    public virtual ICollection<Member> SecondaryMembers { get; set; } 
} 

Ogni membro potenzialmente appartiene a un singolo gruppo principale, e opzionalmente molte squadre secondarie. Il seguente codice demo genera l'eccezione:

using (IDemoContext dbi = new DemoContext()) 
     { 
      var members = 
       (from member in dbi.Members 
       select new 
       { 
        Name = member.Name, 
        Team = member.PrimaryTeam.Name, 
        SecondaryTeams = from secondaryTeam in member.SecondaryTeams 
         join primaryMember in dbi.Members 
         on secondaryTeam.ID equals primaryMember.PrimaryTeamID 
         into secondaryTeamMembers 
         select new 
         { 
          Name = secondaryTeam.Name, 
          Count = secondaryTeamMembers.Count() 
         } 
       }).ToList(); 
     } 

Se cambio la prima linea a:

using (DemoContext dbi = new DemoContext()) 

quindi la query esegue perfettamente.

Quindi le mie domande sono:

  1. Perché funziona attraverso DemoContext e non IDemoContext?
  2. Come cambio IDemoContext in modo che questa query funzioni tramite l'interfaccia?

risposta

5

Provare a sostituire dbi.Members con una variabile locale nella query.

using (IDemoContext dbi = new DemoContext()) 
    { 
     IQueryable<Member> memberSet = dbi.Members; 

     var members = 
      (from member in memberSet 
      select new 
      { 
       Name = member.Name, 
       Team = member.PrimaryTeam.Name, 
       SecondaryTeams = from secondaryTeam in member.SecondaryTeams 
        join primaryMember in memberSet 
        on secondaryTeam.ID equals primaryMember.PrimaryTeamID 
        into secondaryTeamMembers 
        select new 
        { 
         Name = secondaryTeam.Name, 
         Count = secondaryTeamMembers.Count() 
        } 
      }).ToList(); 
    } 
+0

Con questa modifica ora getta una nuova eccezione: oggetto di tipo 'System.Data.Objects.ObjectQuery'1 [DemoApp.Member] "non può essere convertito in tipo" System.Data.Entity.IDbSet'1 [DemoApp.Member] ". Questa eccezione viene generata sia su IDemoContext che su DemoContext. – Beyers

+0

@Beyers Fondamentalmente 'memberet' deve essere di tipo' IQueryable '. Risposta aggiornata – Eranga

+0

Impressionante, funziona al 100% ed è una soluzione migliore della mia soluzione alternativa con dbi.Members.Include (i => i.SecondaryTeams). Ancora interessato a sapere esattamente perché non riesce attraverso l'interfaccia e non attraverso DBContext. – Beyers

0

trovato la soluzione, il trucco è stato quello di includere SecondaryTeams della query:

using (IDemoContext dbi = new DemoContext()) 
    { 
    var memberset = dbi.Members.Include(i => i.SecondaryTeams); 
    var members = 
     (from member in memberset 
     select new 
     { 
      Name = member.Name, 
      Team = member.PrimaryTeam.Name, 
      SecondaryTeams = from secondaryTeam in member.SecondaryTeams 
           join primaryMember in memberset 
       on secondaryTeam.ID equals primaryMember.PrimaryTeamID 
       into secondaryTeamMembers 
       select new 
       { 
        Name = secondaryTeam.Name, 
        Count = secondaryTeamMembers.Count() 
       } 
     }).ToList(); 
    } 
Problemi correlati