我真的可以使用一些帮助,我有以下SQL查询可以工作,并一直试图将其转换为实体框架无济于事。我使用的是方法而不是其他选项,我认为这就是你说的。
无论如何SQL都是
SELECT c.ACCOUNTID,
c.TOACCOUNTID,
fa.ACCOUNTNAME, ta.ACCOUNTNAME,
p.PAYEENAME
FROM checking AS c
LEFT JOIN
ACCOUNT AS fa ON c.ACCOUNTID = fa.ACCOUNTID
LEFT JOIN
ACCOUNT AS ta ON c.TOACCOUNTID = ta.ACCOUNTID
LEFT JOIN
PAYEE AS p ON c.PAYEEID = p.PAYEEID
WHERE c.ACCOUNTID == 1 OR
c.TOACCOUNTID == 1;
到目前为止,我已成功实现这一目标。
var checking =
db.Transactions
.Where(item => item.ACCOUNTID == LookupAccount || item.TOACCOUNTID == LookupAccount)
.GroupJoin(db.PAYEE,
transaction => transaction.PAYEEID,
payee => payee.PAYEEID,
(check, payee) => new { Payee = payee }
).SelectMany(
transaction => transaction.Payee.DefaultIfEmpty(),
(transaction, payee) => new { Payee = payee })
.Select(item => new
{
ToAccount = item.ToAccount.AccountName
FromAccount = item.FromAccount.AccountName
Withdrawal = 0,
Deposit = 0,
Payee = item.Payee.PAYEENAME
}).ToList();
我现在遇到的问题是,我不确定我是否理解联接是如何以这种方式工作的,每当我试图让其他两个联接时,我最终都会落在我的脸上。
当我将此添加到上面的代码时,收款人部分出了问题,我不明白为什么。我知道它与select new {}部分有关,我真的可以使用一些帮助来理解它是如何工作的。
.Join(db.ACCOUNT,
check => check.ACCOUNTID,
account => account.ACCOUNTID,
(check, fromaccount) => new { FromAccount = fromaccount }
)
交易
public partial class Transaction
{
[Key]
public int Id { get; set; }
public int AccountID { get; set; }
public int? ToAccountId { get; set; }
public int PayeeId { get; set; }
[Column(TypeName = "numeric")]
public decimal TransAmount { get; set; }
[Column(TypeName = "numeric")]
public decimal ToTransAmount { get; set; }
public virtual Account Account { get; set; }
}
帐户
public partial class Account
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Account()
{
Transaction = new HashSet<Transaction>();
}
[Key]
public int AccountId { get; set; }
[Required]
[StringLength(150)]
public string AccountName { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Transaction> Transaction { get; set; }
}
答案 0 :(得分:0)
这不会作为评论,但它可能会让你更进一步。您的tx类中有2个FK,因此您需要2个导航属性:
public partial class Transaction
{
public int Id { get; set; } // Key by convention
public int FromAccountID { get; set; }
public virtual Account FromAccount { get; set; }
public int? ToAccountId { get; set; }
public virtual Account ToAccount { get; set; }
public int PayeeId { get; set; }
public virtual Payee Payee { get; set; }
public decimal TransAmount { get; set; }
public decimal ToTransAmount { get; set; }
}
public partial class Account
{
public Account()
{
Transaction = new HashSet<Transaction>();
}
public int AccountId { get; set; } // Key by convention
[Required]
[StringLength(150)]
public string AccountName { get; set; }
[InverseProperty("FromAccount")]
public virtual ICollection<Transaction> TransactionsFrom { get; set; }
[InverseProperty("ToAccount")]
public virtual ICollection<Transaction> TransactionsTo { get; set; }
}
现在您的查询变为:
var checking =
db.Transactions
.Include(tx => tx.Payee)
.Include(tx => tx.FromAccount)
.Include(tx => tx.ToAccount)
.Where(tx => tx.FromAccountId == lookupAccountId || tx.ToAccountId == lookupAccountId)
.Select(tx => new
{
ToAccountName = tx.ToAccount.AccountName
FromAccountName = tx.FromAccount.AccountName
Withdrawal = tx.ToTransAmount,
Deposit = tx.TransAmount,
PayeeName = tx.Payee.PAYEENAME
}).ToList();
https://coding.abel.nu/2012/06/dont-use-linqs-join-navigate/
答案 1 :(得分:0)
我已经创建了这个作为答案,对于任何其他可能遇到此问题且正在学习语法的人。
我没有让它发挥作用的原因实际上是由于缺乏EF在加入时的实际效果。
Transactions
.Join(Accounts,
tr => tr.AccountId,
ac => ac.AccountId,
(tr, ac) => new { Transaction = tr, ac})
.GroupJoin(Accounts,
tr => tr.Transaction.ToAccountId,
ta => ta.AccountId,
(tr, ta) => new { Transaction = tr.Transaction, Account = ta, FromAccount = tr.ac})
.SelectMany(
transaction => transaction.Account.DefaultIfEmpty()
,(transaction, account) => new { tt = transaction.Transaction, ToAccount = account, FromAccount = transaction.FromAccount}
)
.GroupJoin(Payees,
tr => tr.tt.PayeeId,
payee => payee.PAYEEID,
(tr, payee) => new { Transaction = tr, Payee = payee })
.SelectMany(
transaction => transaction.Payee.DefaultIfEmpty(),
(transaction, payee) => new {transaction = transaction.Transaction.tt, FromAccount = transaction.Transaction.FromAccount, ToAccount = transaction.Transaction.ToAccount, Payee = payee })
.Where (x=> x.FromAccount.AccountId == 1 || x.ToAccount.AccountId == 1)
.Select(item => new
{
item.transaction.Id,
TransDate = item.transaction.TRANSDATE,
Number = item.transaction.TransactionNumber,
Payee = item.Payee.PAYEENAME,
Status = item.transaction.Status,
Category = item.transaction.CategoryId,
FromAccount = item.FromAccount.AccountName,
ToAccount = item.ToAccount.AccountName,
Withdrawal = 0,
Deposit = 0,
Notes = item.transaction.Notes
})
我不理解的部分是代码中的关系,来自连接以及Selects如何接管并通过对象创建层次结构。我真的希望我可以在这里使用导航,但是根据我对导航的理解,需要在列之间建立关系,并且几乎所有在这里连接的字段都可以为null,因此外键不能满足要求导航。
我仍然相信有更好的方法,但是现在我把它放在那些仍在学习并希望看到有效解决方案的人身上。