You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linq2db中QueryExpressionMethod关联报空值错误,键关联正常

Linq2db中用QueryExpressionMethod替换Association键关联引发异常的问题

我尝试将Linq2db中基于键的Association关联方式改为QueryExpressionMethod形式(用于优化其他代码),但遇到了问题:

可正常运行的代码

[Association( CanBeNull = true, ThisKey = nameof( AccountId ), OtherKey = nameof( Common.Account.AccountId ) )]
public List<AccountPayment> AccountPayments { get; set; }

无法运行的代码

[Association( CanBeNull = true, QueryExpressionMethod = nameof (LatestPaymentImpl) )]
public List<AccountPayment> AccountPayments { get; set; }

public static Expression<Func<Account, IDataContext, IQueryable<Repositories.Models.Common.AccountPayment>>> LatestPaymentImpl()
{
    return ( ap, db ) => db.GetTable<AccountPayment>().Where( acc => acc.AccountId == ap.AccountId );
}

抛出的异常信息

"reason": "ArgumentException",
"message": "Value cannot be null.\r\nParameter name: arg0",
"status": "badRequest",
"stackTrace": " at System.Linq.Expressions.Expression.Call(Expression instance,
MethodInfo method, Expression arg0, Expression arg1, Expression
arg2)\r\n at
LinqToDB.Linq.Builder.TableBuilder.AssociatedTableContext.GetAssociationQueryExpression(Expression
dataContextExpr, Expression parentObjExpression, Type parentType,
Expression parentTableExpression, LambdaExpression queryMethod)\r\n

at
LinqToDB.Linq.Builder.TableBuilder.AssociatedTableContext..ctor(ExpressionBuilder
builder, TableContext parent, AssociationDescriptor association)\r\n

at
LinqToDB.Linq.Builder.TableBuilder.TableContext.b__71_6(AssociationDescriptor
a)\r\n at
System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()\r\n at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable1
source)\r\n at
LinqToDB.Linq.Builder.TableBuilder.TableContext.GetAssociation(Expression
expression, Int32 level)\r\n at
LinqToDB.Linq.Builder.TableBuilder.TableContext.GetAssociation(Expression
expression, Int32 level)

环境信息

  • Linq2db版本:2.7.0

涉及的实体类代码

Account类

[Table( Name = "Account", Schema = "Common" )]
public class Account : ISoftDeletableRepositoryModel
{
    #region Members

    [Column( "AccountId" ), Identity, PrimaryKey]
    public Guid AccountId { get; set; }

    [Column( "Deleted", SkipOnUpdate = true ), NotNull]
    public bool Deleted { get; set; }

    [Column( "Name" ), NotNull]
    public string Name { get; set; }

    [Association( CanBeNull = true, ThisKey = nameof( AccountId ), OtherKey = nameof( Security.UserAccount.AccountId ) )]
    public UserAccount UserAccount { get; set; }

    [Association( CanBeNull = true, ThisKey = nameof( AccountId ), OtherKey = nameof( Common.Account.AccountId ) )]
    public List<AccountPayment> LatestAccountPayment { get; set; }
}

AccountPayment类

[Table( Name = "AccountPayment", Schema = "Common" )]
public class AccountPayment : ISoftDeletableRepositoryModel
{
    #region Members

    [Column( "AccountPaymentId" ), Identity, PrimaryKey]
    public Guid AccountPaymentId { get; set; }

    [Column( "Deleted", SkipOnUpdate = true ), NotNull]
    public bool Deleted { get; set; }

    [Column( "AccountId" ), NotNull]
    public Guid AccountId { get; set; }

    [Column( "PackageId" ), Nullable]
    public Guid? PackageId { get; set; }

    [Column( "Provider" ), NotNull]
    public string Provider { get; set; }

    [Column( "CustomerId" ), Nullable]
    public string CustomerId { get; set; }

    [Column( "SubscriptionId" ), Nullable]
    public string SubscriptionId { get; set; }

    [Column( "PaymentMethodToken" ), Nullable]
    public string PaymentMethodToken { get; set; }

    [Column( "Status" ), NotNull]
    public string Status { get; set; }

    [Column( "CreatedOn" ), NotNull]
    public DateTime CreatedOn { get; set; }

    [Column( "ValidUntil" ), Nullable]
    public DateTime? ValidUntil { get; set; }

    [Column( "CanceledOn" ), Nullable]
    public DateTime? CanceledOn { get; set; }

    #endregion Members

    #region Associations

    [Association( CanBeNull = true, ThisKey = nameof( AccountId ), OtherKey = nameof( Common.Account.AccountId ) )]
    public Account Account { get; set; }

    [Association( CanBeNull = true, ThisKey = nameof( PackageId ), OtherKey = nameof( Sales.Package.PackageId ) )]
    public Package Package { get; set; }

    #endregion Associations
}

查询示例代码

query = from q in query
        join pa in db.ProgramAssigns on new { c = q.ProgramId, s = identityContext.UserId } equals new { c = pa.ProgramId, s = pa.AssigneeId } into paa
        from pa in paa.DefaultIfEmpty()
        where q.Deleted == false && ( pa != null && pa.Assigner.UserAccount.Account.LatestAccountPayment != null && pa.Assigner.UserAccount.Account.LatestAccountPayment.OrderByDescending(x => x.ValidUntil).FirstOrDefault().ValidUntil > DateTime.Now  )
        select q;

两种实现逻辑完全一致,但我不清楚该如何排查这个异常问题。


内容的提问来源于stack exchange,提问作者galaxyfreak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 23:05:27