【问题标题】:removing joins from Linq query从 Linq 查询中删除连接
【发布时间】:2011-04-03 09:51:12
【问题描述】:

我有两个这样的实体:

[Table("tblAccount")]
public class Account
{      
    [Key]
    [Column("Creditor Registry ID", Order = 0)]
    public int CreditRegistryId { get; set; }

    [Key]
    [Required]
    [Column("Account No", Order = 1)] 
    public int AccountNo { get; set; }

    [Column("Minimum Installment")]
    public decimal MinimumInstallment { get; set; }

    [Column("Account Status Date")]
    public DateTime AccountStatusDate { get; set; }

    [Required]
    [Column("Account Type")]
    public string AccountType { get; set; }

    public virtual ICollection<AccountOwner> AccountOwners { get; set; }
}

[Table("tblAccountOwner")]
public class AccountOwner
{
    [Key]
    [ForeignKey("Account")]
    [Column("Creditor Registry ID", Order = 0)]   
    public int CreditorRegistryId { get; set; }


    [Key]
    [ForeignKey("Account")]
    [Column("Account No", Order = 1)]           
    public int AccountNo { get; set; }

    [Key]
    [Column("Account Owner Registry ID", Order = 2)] 
    public long AccountOwnerRegistryId { get; set; }

    public virtual Account Account { get; set; }
}

我想将以下查询转换为无需加入即可工作,因为帐户实体具有 accountOwners 并且 accounOwner 具有帐户导航属性(主键/外键关系)

var ownerRegId = 731752693037116688L;
var excludeTypes = new[] { 'CA00', 'CA01', 'CA03', 'CA04', 'CA02', 'PA00', 'PA01', 'PA02', 'PA03', 'PA04' };
var maxStateChangeMonth = 4;
var excludeStatusId = 999;
var SumOfMonthlyPayments =
    context.Accounts
           .Join(context.AccountOwners,
                 a => new { CreditorRegistryId = a.CreditRegistryId, a.AccountNo },
                 ao => new { ao.CreditorRegistryId, ao.AccountNo },
                 (a, ao) => new { Account = a, AccountOwner = ao })
           .Where(x => x.AccountOwner.AccountOwnerRegistryID == ownerRegId
                    && !excludeTypes.Contains(x.Account.AccountType)
                    && (x.Account.StateChangeDate == null || x.Account.StateChangeDate.Month - DateTime.Now.Month <= maxStateChangeMonth)
                    && x.Account.AccountStatusID != excludeStatusId)
           .Sum(x => Math.Abs(x.Account.MinimumInstallment));

按照 Sergi 的建议,我发现了这个:

var sum = (from account in context.Accounts
           from owner in account.AccountOwners
           where (owner.AccountOwnerRegistryId == ownerRegistryId
               && !excludeTypes.Contains(account.AccountType)
               && (account.StateChangeDate == null ||
                   (account.StateChangeDate.Month - DateTime.Now.Month)
                       <= maxStateChangeMonth)
               && account.AccountStatusId != excludeStatusId
               && (includeMortgage.Contains(account.AccountType) || 
                    account.AccountType.Contains("Mortgage")))
            select account.MinimumInstallment)
               .Sum(minimumInstallment => Math.Abs(minimumInstallment));

我添加了另一个 && 子句

 && (includeMortgage.Contains(account.AccountType) ||
    account.AccountType.Contains("Mortgage") 

但现在我明白了:

The cast to value type 'Decimal' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.

谢谢

【问题讨论】:

    标签: asp.net linq asp.net-mvc-3 linq-to-entities


    【解决方案1】:

    正如您所提到的,您可以使用导航属性而不是连接,因此您可以尝试以下操作:

    var sum = (from account in context.Accounts
               from owner in account.AccountOwners
               where (owner.AccountOwnerRegistryID == ownerRegId
                   && !excludeTypes.Contains(account.AccountType)
                   && (account.StateChangeDate == null || 
                      (account.StateChangeDate.Month - DateTime.Now.Month)
                           <= maxStateChangeMonth)
                   && account.AccountStatusID != excludeStatusId)
               select account.MinimumInstallment)
                   .Sum(minimumInstallment => Math.Abs(minimumInstallment));
    

    两个“串联”的from 子句等价于Linq 中的SelectMany 方法。

    【讨论】:

    • 谢谢。我做了一些改变并添加了一个新的过滤器,但现在我得到了:转换为值类型“十进制”失败,因为物化值为空。结果类型的泛型参数或查询必须使用可为空的类型。请查看更新后的问题
    • @DotnetSparrow - 这可能意味着select account.MinimumInstallment) 行正在返回null,即,que 查询没有返回任何结果并且Sum 传递了null。您可以尝试在没有.Sum(...) 行的情况下运行查询吗?你有任何结果吗?结果中有null结果吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    • 2011-10-28
    相关资源
    最近更新 更多