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

本文关键字:查询 异常 DbContext 接口 访问 | 更新日期: 2023-09-27 18:20:46

我创建了一个DbContext类实现的接口,这使我能够创建一个用于单元测试的假数据库上下文。到目前为止,这对我所有的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.

通过接口执行LINQ查询会引发上述异常,但是,当直接在我的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 (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();
        }

如果我将第一行更改为:

using (DemoContext dbi = new DemoContext())

那么查询就完美地执行了。

所以我的问题是:

  1. 为什么它通过DemoContext而不是IDemoContext工作
  2. 如何更改IDemoContext以使该查询通过接口工作

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

尝试在查询中用局部变量替换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();
    }

找到了解决方案,诀窍是在查询中包含SecondaryStream:

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