我在项目中使用linq2db ORM,并且有以下查询:
pushstate
和Build方法如下:
var query =
from t in _db.Transactions
from a in _db.Accounts.LeftJoin(a => a.Id == t.AccountId)
from u in _db.Users.LeftJoin(u => u.Id == a.UserId)
select Transaction.Build(t, u, a);
“用户”表包含“全名”列,我想知道是否可以按用户的全名来过滤交易吗?
public static Transaction Build(Transaction transaction, User user, Account account)
{
account.User = user;
transaction.Account = account;
return transaction;
}
是否可以用linq2db实现它?
答案 0 :(得分:1)
在工厂方法调用Transaction.Build(t, u, a)
之后,linq2db丢失了有关字段映射的信息,查询变得仅对实现有利,而对过滤却无济于事。对于任何当前可用的LINQ提供程序都是如此。
使用linq2db可以使代码可重用的方法-使用Transaction.Build
重写函数ExpressionMethodAttribute
:
static Func<Transaction, User, Account, Transaction> _buildFunc;
static Expression<Func<Transaction, User, Account, Transaction>> BuildImpl()
{
return (Transaction transaction, User user, Account account) =>
new Transaction
{
Id = transaction.Id,
... // copy all needed fields
Account = new Account
{
Id = account.Id,
... // copy all needed fields
User = user
}
}
);
}
[ExpressionMethod(nameof(BuildImpl))]
public static Transaction Build(Transaction transaction, User user, Account account)
{
// we left function usable even for non-query scenarios.
_buildFunc ??= BuildImpl().Compile();
return _buildFunc(transaction, user, account);
}
进行这些操作后,可以在Transaction.Build
调用之后过滤查询。
在后台,linq2db将找到ExpressionMethodAttribute
声明,并用Transaction.Build
函数中定义的Expression替换BuildImpl
调用。在分析LINQ查询之前,将其示意图化为以下变体:
var query =
from t in _db.Transactions
from a in _db.Accounts.LeftJoin(a => a.Id == t.AccountId)
from u in _db.Users.LeftJoin(u => u.Id == a.UserId)
select new Transaction
{
Id = t.Id,
... // copy all needed fields
Account = new Account
{
Id = a.Id,
... // copy all needed fields
User = u
}
};