Linq2db:按嵌套 属性 字段过滤
Linq2db: filter by nested property field
我在我的项目中使用了 linq2db ORM,我有以下查询:
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;
}
用户 table 包含全名列,我想知道是否可以按用户全名过滤交易?
if (!string.IsNullOrWhiteSpace(userNameFilter))
{
query = query.Where(t => t.Account.User.FullName.Contains(userNameFilter));
}
可以用linq2db实现吗?
在工厂方法调用后 Transaction.Build(t, u, a)
,linq2db 丢失了有关字段映射的信息,并且查询变得仅适用于物化而不适用于过滤。对于任何当前可用的 LINQ 提供程序都是如此。
您可以使用 linq2db 做什么来使代码可重用 - 使用 ExpressionMethodAttribute
:
重写您的函数 Transaction.Build
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
声明并用 BuildImpl
函数中定义的表达式替换 Transaction.Build
调用。示意性地在分析 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
}
};
我在我的项目中使用了 linq2db ORM,我有以下查询:
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;
}
用户 table 包含全名列,我想知道是否可以按用户全名过滤交易?
if (!string.IsNullOrWhiteSpace(userNameFilter))
{
query = query.Where(t => t.Account.User.FullName.Contains(userNameFilter));
}
可以用linq2db实现吗?
在工厂方法调用后 Transaction.Build(t, u, a)
,linq2db 丢失了有关字段映射的信息,并且查询变得仅适用于物化而不适用于过滤。对于任何当前可用的 LINQ 提供程序都是如此。
您可以使用 linq2db 做什么来使代码可重用 - 使用 ExpressionMethodAttribute
:
Transaction.Build
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
声明并用 BuildImpl
函数中定义的表达式替换 Transaction.Build
调用。示意性地在分析 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
}
};