C# 当通过接口访问时,DbContext在查询时引发异常

C# 当通过接口访问时,DbContext在查询时引发异常,c#,.net,linq,entity-framework-4.1,C#,.net,Linq,Entity Framework 4.1,我已经创建了DbContext类实现的接口,这使我能够为单元测试创建一个假的db上下文。到目前为止,这适用于所有LINQ查询,但有一个例外: Unable to create a constant value of type 'DemoApp.Member'. Only primitive types ('such as Int32, String, and Guid') are supported in this context. using (IDemoContext dbi = new

我已经创建了DbContext类实现的接口,这使我能够为单元测试创建一个假的db上下文。到目前为止,这适用于所有LINQ查询,但有一个例外:

Unable to create a constant value of type 'DemoApp.Member'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
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();
        }
通过接口执行LINQ查询会引发上述异常,但是,当直接在my DBContext上执行完全相同的查询时,查询的效果为100%。以下是界面和相关演示代码定义:

    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; }
}
如果我将第一行更改为:

using (DemoContext dbi = new DemoContext())
然后,查询将完美地执行

因此,我的问题是:

  • 为什么它通过DemoContext而不是IDemoContext工作
  • 如何更改IDemoContext以使此查询通过接口工作

  • 尝试在查询中用局部变量替换
    dbi.Members

        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();
        }
    
    使用(IDemoContext dbi=new DemoContext())
    {
    IQueryable memberSet=dbi.Members;
    变量成员=
    (来自memberSet中的成员)
    选择新的
    {
    Name=member.Name,
    团队=member.PrimaryTeam.Name,
    SecondarySteams=来自member.SecondarySteams中的SecondarySteams
    在成员集中加入primaryMember
    在secondaryTeam.ID上等于primaryMember.PrimaryTeamID
    成为第二团队成员
    选择新的
    {
    Name=secondaryTeam.Name,
    Count=secondaryTeamMembers.Count()
    }
    }).ToList();
    }
    
    找到了解决方案,诀窍是在查询中包含辅助团队:

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

    通过此更改,它现在引发了一个新的异常:“System.Data.Objects.ObjectQuery
    1[DemoApp.Member]”类型的对象无法转换为“System.Data.Entity.IDbSet
    1[DemoApp.Member]”类型。IDemoContext和DemoContext都会引发此异常。@Beyers基本上
    memberset
    的类型必须是
    IQueryable
    。更新的答案。真棒,这是一个100%有效的解决方案,比我使用dbi.Members.Include(i=>i.SecondaryTeams)的解决方案更好。仍然有兴趣知道它为什么会通过接口而不是通过DBContext失败。@Beyers我不知道它为什么会失败,但这是一个很好的例子来说明单元测试依赖于EF的代码不会产生预期的结果。