2012-01-19 35 views
6

Tôi đã tạo giao diện mà lớp DbContext của tôi triển khai, điều này cho phép tôi tạo ngữ cảnh db giả để kiểm tra đơn vị. Này hoạt động tốt cho tất cả LINQ của tôi truy vấn cho đến nay nhưng một, nơi tôi có được ngoại lệ sau đây:DbContext ném ngoại lệ trên truy vấn khi được truy cập thông qua giao diện

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

Thực thi truy vấn LINQ thông qua giao diện ném ngoại lệ trên, tuy nhiên khi thực hiện cùng một truy vấn chính xác trực tiếp trên DBContext của tôi truy vấn hoạt động 100%. Dưới đây là các định nghĩa về mã demo và giao diện có liên quan:

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; } 
} 

Mỗi thành viên có thể thuộc về một nhóm chính và nhiều nhóm phụ tùy chọn. Các code demo sau ném ngoại lệ:

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(); 
     } 

Nếu tôi thay đổi dòng đầu tiên:

using (DemoContext dbi = new DemoContext()) 

sau đó truy vấn thực hiện một cách hoàn hảo.

Vì vậy, câu hỏi của tôi là:

  1. Tại sao nó làm việc thông qua DemoContext và không IDemoContext?
  2. Làm cách nào để thay đổi IDemoContext để truy vấn này hoạt động thông qua giao diện?

Trả lời

5

Thử thay thế dbi.Members bằng biến cục bộ trong truy vấn.

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

Với sự thay đổi này nó bây giờ ném một ngoại lệ mới: Đối tượng của loại 'System.Data.Objects.ObjectQuery'1 [DemoApp.Member] 'không thể chuyển đổi thành loại' System.Data.Entity.IDbSet'1 [DemoApp.Member] '. Ngoại lệ này được ném trên cả IDemoContext cũng như DemoContext. – Beyers

+0

@Beyers Về cơ bản 'memberset' phải thuộc loại' IQueryable '. Đã cập nhật câu trả lời. – Eranga

+0

Tuyệt vời, điều này làm việc 100% và là một giải pháp tốt hơn so với giải pháp của tôi với dbi.Members.Include (i => i.SecondaryTeams). Vẫn quan tâm để biết chính xác lý do tại sao nó không thông qua giao diện và không thông qua DBContext. – Beyers

0

Tìm thấy các giải pháp, các trick là để Bao gồm SecondaryTeams trong truy vấn:

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(); 
    } 
Các vấn đề liên quan