我有以下型号:
public class Account
{
public Guid Id{ get; set; }
[Filterable]
public string Code{ get; set; }
[Filterable]
public string AccountStatus { get; set; }
}
正在根据AccountStatus
和StartDate
的值计算属性EndDate
的值,因此在我的存储库中的Linq查询中,我有以下内容:
public IEnumerable<Account> Get(QueryClause<Account> queryClause, out ForGetCollectionOptions forGetCollectionOptions)
{
using (_dbContext)
{
var result = (
from account in _dbContext.Accounts
select new Account
{
Id = account.ID,
Code = account.Code.Trim(),
AccountStatus = StatusCalculator.GetStatus(account.StartDate, account.EndDate)
}
ApplyFilterClause(ref result, queryClause.FilterClause);
}
}
为了计算帐户状态,我们有以下内容: 公共枚举状态 { 不活动, 活性, 未来 }
public static class StatusCalculator
{
public static string GetStatus(DateTime? startDate, DateTime? endDate)
{
var now = DateTime.Now;
if (startDate != null && startDate > now)
{
return Status.Future.ToString().ToLower();
}
if (startDate != null && endDate == null)
{
return Status.Active.ToString().ToLower();
}
return Status.Inactive.ToString().ToLower();
}
}
问题在于,当我尝试过滤例如'inactive'的accountStatus时,我得到以下运行时警告:
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'where (GetStatus([account].StartDate, [account].EndDate) == "inactive")' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
The LINQ expression 'Count()' could not be translated and will be evaluated locally.
因为无法转换计算的属性,将在没有该条件的情况下发送查询并检索所有数据,然后在本地应用该过滤器,这将损害性能。
如何为where子句添加自定义翻译以及排序和计数?
答案 0 :(得分:1)
您计算该属性的业务逻辑目前很简单,因此可以内联:
public IEnumerable<Account> Get(QueryClause<Account> queryClause, out ForGetCollectionOptions forGetCollectionOptions)
{
using (_dbContext)
{
var result = (
from account in _dbContext.Accounts
select new Account
{
Id = account.ID,
Code = account.Code.Trim(),
AccountStatus = (account.StartDate != null && account.EndDate == null)
? "Active"
: (account.StartDate != null && account.StartDate > DateTime.Now)
? "Future"
: "Inactive"
}
ApplyFilterClause(ref result, queryClause.FilterClause);
}
}
这应该使EF能够将其转换为CASE语句,如:
SELECT foo
,(CASE
WHEN t.StartDate IS NOT NULL...
WHEN t.StartDate IS NOT NULL AND t.StartDate > GetDate()
ELSE ...
)
FROM bar