从Linq查询中删除联接

时间:2011-04-03 09:51:12

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

我有两个这样的实体:

[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));

我添加了另一个&amp;&amp;条款

 && (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.

由于

1 个答案:

答案 0 :(得分:0)

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

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方法。