Skip to content

多表Select使用导航属性会抛出StackOverflow #2259

Description

@ROMYIM

问题描述及重现代码:

表a,b,c,d。a,b一对多,a,c表一对多,b,d一对一。
a,b,c三表需要返回字段,作为主表,固定连接。d表只用于某些特定字段的查询,做动态连接以及where条件判断。
由于d表的字段过滤不是一定会触发,所以d表的过滤条件我想根据c表的导航属性做连接并判断。
伪代码如下:
var query = freeSql.Select<a, b, c>()
.LeftJoin((a,b,c)=>a.B = b.B)
.LeftJoin((a,b,c)=>a.C = c.C)
.WhereIf(条件成立, (a,b,c) => b.d.D = 特殊条件)

表a实体

[Table(Name = "ip_consulting_support", DisableSyncStructure = true)]
public partial class IpConsultingSupport {

    /// <summary>
    /// 主键
    /// </summary>
    [Column(Name = "id", IsPrimary = true, IsIdentity = true)]
    public int Id { get; set; }

    /// <summary>
    /// 预算
    /// </summary>
    [Column(Name = "budget", DbType = "money")]
    public decimal Budget { get; set; } = 0M;

    /// <summary>
    /// 业务类型
    /// </summary>
    [Column(Name = "business_type_id", StringLength = 50, IsNullable = false)]
    public string BusinessTypeId { get; set; } = "";

    /// <summary>
    /// 完结日期
    /// </summary>
    [Column(Name = "complete_time")]
    public DateOnly? CompleteTime { get; set; }

    /// <summary>
    /// 创建时间
    /// </summary>
    [Column(Name = "creation_time", InsertValueSql = "getdate()")]
    public DateTime CreationTime { get; set; }

    /// <summary>
    /// 创建用户id
    /// </summary>
    [Column(Name = "creator", StringLength = 50, IsNullable = false)]
    public string Creator { get; set; } = "";

    /// <summary>
    /// CRM申请号
    /// </summary>
    [Column(Name = "crm_application_no", StringLength = 50, IsNullable = false)]
    public string CrmApplicationNo { get; set; } = "";

    /// <summary>
    /// CRM申请人
    /// </summary>
    [Column(Name = "crm_applicant", StringLength = 1000, IsNullable = false)]
    public string CrmApplicant { get; set; } = "";

    /// <summary>
    /// CRM申请日期
    /// </summary>
    [Column(Name = "crm_apply_time")]
    public DateTime? CrmApplyTime { get; set; }

    /// <summary>
    /// 客户id
    /// </summary>
    [Column(Name = "customer_id", StringLength = 50, IsNullable = false)]
    public string CustomerId { get; set; } = "";

    /// <summary>
    /// 请求支持截止时间
    /// </summary>
    [Column(Name = "deadline")]
    public DateTime? Deadline { get; set; }

    /// <summary>
    /// 主承办人id
    /// </summary>
    [Column(Name = "main_undertaker_id", StringLength = 50, IsNullable = false)]
    public string MainUndertakerId { get; set; } = "";

    /// <summary>
    /// 二级产品
    /// </summary>
    [Column(Name = "product_name", StringLength = 50, IsNullable = false)]
    public string ProductName { get; set; } = "";

    /// <summary>
    /// 备注
    /// </summary>
    [Column(Name = "remark", StringLength = -2, IsNullable = false)]
    public string Remark { get; set; } = "";

    /// <summary>
    /// 结果说明
    /// </summary>
    [Column(Name = "result_description", StringLength = -2, IsNullable = false)]
    public string ResultDescription { get; set; } = "";

    /// <summary>
    /// 支持编号
    /// </summary>
    [Column(Name = "support_no", StringLength = 50, IsNullable = false)]
    public string SupportNo { get; set; } = "";

    /// <summary>
    /// 支持结果
    /// </summary>
    [Column(Name = "support_result", StringLength = 50, IsNullable = false)]
    public string SupportResult { get; set; } = "";

    /// <summary>
    /// 支持状态
    /// </summary>
    [Column(Name = "support_status", InsertValueSql = "")]
    public string SupportStatus { get; set; } = "";

    /// <summary>
    /// 支持类型
    /// </summary>
    [Column(Name = "support_type", StringLength = 50, IsNullable = false)]
    public string SupportType { get; set; } = "";

    /// <summary>
    /// 承办部门ID
    /// </summary>
    [Column(Name = "undertake_dept_id", StringLength = 50, IsNullable = false)]
    public string UndertakeDeptId { get; set; } = "";

    /// <summary>
    /// 更新时间
    /// </summary>
    [Column(Name = "update_time", InsertValueSql = "getdate()")]
    public DateTime UpdateTime { get; set; }

    /// <summary>
    /// 更新用户ID
    /// </summary>
    [Column(Name = "updater", StringLength = 50, IsNullable = false)]
    public string Updater { get; set; } = "";

    /// <summary>
    /// 需求
    /// </summary>
    [Column(Name = "request", IsNullable = false)]
    public string Request { get; set; } = "";

}

表b实体

[Table(Name = "ip_work_allocation", DisableSyncStructure = true)]
public partial class IpWorkAllocation {

    /// <summary>
    /// 主键
    /// </summary>
    [Column(Name = "id", IsPrimary = true, IsIdentity = true)]
    public int Id { get; set; }

    /// <summary>
    /// 贡献占比
    /// </summary>
    [Column(Name = "contribution_ratio", DbType = "decimal(5,2)")]
    public decimal ContributionRatio { get; set; } = 0.00M;

    /// <summary>
    /// 添加人
    /// </summary>
    [Column(Name = "creator", StringLength = 50, IsNullable = false)]
    public string Creator { get; set; } = "";

    /// <summary>
    /// 添加时间
    /// </summary>
    [Column(Name = "creation_time",  IsNullable = false)]
    public DateTime CreationTime { get; set; }

    /// <summary>
    /// 支持ID
    /// </summary>
    [Column(Name = "supporting_id")]
    public int SupportingId { get; set; }

    /// <summary>
    /// 修改时间
    /// </summary>
    [Column(Name = "update_time", IsNullable = false)]
    public DateTime UpdateTime { get; set; }

    /// <summary>
    /// 修改人
    /// </summary>
    [Column(Name = "updater", StringLength = 50)]
    public string Updater { get; set; } = "";

    /// <summary>
    /// 用户id
    /// </summary>
    [Column(Name = "user_id", StringLength = 50, IsNullable = false)]
    public string UserId { get; set; } = "";

    /// <summary>
    /// 用户信息
    /// </summary>
    [Navigate(nameof(UserId))]
    public virtual SysUserInfo? UserInfo { get; set; }

}

表c实体

[ Table(Name = "case_info", DisableSyncStructure = true)]
	public partial class CaseInfo  {

		/// <summary>
		/// 案件ID
		/// </summary>
		[ Column(Name = "case_id", StringLength = 50, IsPrimary = true, IsNullable = false)]
		public string Id { get; set; } = Guid.NewGuid().ToString().ToUpper();
		
                [ Column(Name = "volume")]
		public string Volume { get; set; }
}

表d实体

[ Table(Name = "sys_user_info", DisableSyncStructure = true)]
	public partial class SysUserInfo {

		[ Column(Name = "user_id", StringLength = 50, IsPrimary = true, IsNullable = false)]
		public string UserId { get; set; }

		[ Column(Name = "dept_id", StringLength = 500)]
		public string DeptId{ get; set; }
}

查询构建

var query = freeSql.Select<IpConsultingSupport, IpWorkAllocation, CaseInfo>()
            .WithLock()
            .LeftJoin((s, a, c) => s.Id == a.SupportingId)
            .LeftJoin((s, a, c) => s.Id == c.SupportingId)
            .WhereIf(staffDepartmentIds.Any(), (s, a, c) => staffDepartmentIds.Contains(a.UserInfo!.DeptId));

断点调试发现d表的TableInfo会一直增加,但是On条件为null

Image

数据库版本

Microsoft SQL Server 2019 (RTM-CU32-GDR) (KB5068404) - 15.0.4455.2 (X64)
Oct 7 2025 21:10:15
Copyright (C) 2019 Microsoft Corporation
Standard Edition (64-bit) on Windows Server 2016 Datacenter 10.0 (Build 14393: ) (Hypervisor)

安装的Nuget包

Image

.net framework/. net core? 及具体版本

.net 10

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions