将此属性简化为在谓词中使用

本文关键字:谓词 属性 | 更新日期: 2023-09-27 18:27:16

我有很多Accounts,每个帐户也可以有子帐户。因此,我知道帐户是否为root的方法要归功于ParentId属性中的值
所以我的代码在很多地方都有这样的东西:.Where(acc => acc.ParentId == 0),所以我想创建一个看起来像这样的属性:

public bool IsRootAccount
{
    return a.ParentId == 0;
}

它似乎可以工作,它可以编译,但当运行时,我会得到以下异常:

Load operation failed for query 'GetAccounts'. The specified type member 'IsRootAccount' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.

有没有一种简单的方法可以实现我想要的?

我还考虑过创建一些东西,让它在没有运气的情况下返回Expression<Func<Account, bool>>

编辑:我对IsRootAccount属性的尝试是为了使用类似于.Where(acc => acc.IsRootAccount) 的东西

将此属性简化为在谓词中使用

提供此功能的一种非常简单的方法是使用扩展方法。

试试这样的东西:

public static class AccountEx
{
    public static IQueryable<Account> WhereIsRootAccount(
            this IQueryable<Account> source)
    {
        return source.Where(acc => acc.ParentId == 0);
    }
}

然后,您将用.WhereIsRootAccount()替换.Where(acc => acc.ParentId == 0)的每次使用。

这种方法的优点是它可以与EF一起使用,并且它提供了一种流畅的方式来查询您的根帐户。如果你需要修改根帐户的定义,你也只有一个地方可以进行更改。而且它不会用不必要的代码污染Account类。

我希望这能有所帮助。


根据你的评论,试试这个:

public static class AccountEx
{
    public static EntityQuery<Account> WhereIsRootAccount(
            this EntityQuery<Account> source)
    {
        return source.Where(acc => acc.ParentId == 0);
    }
}

由于EntityQuery<>支持Where,因此它应该仍然可以正常工作。

我发现了一些东西,但我想看看是否还有更好的办法。
我知道EF不知道如何将我的谓词转换为SQL,因为我的属性。所以我不能这样做:

Context.Load(Context.GetAccountsQuery().Where(acc => acc.IsRootAccount), ParentAccountsArrived, null);  

但一旦结果从服务器返回,我确实可以用我的属性进行过滤:

public void LoadParentAccounts()
{
    Context.Load(Context.GetAccountsQuery(), ParentAccountsArrived, null);  
}
void ParentAccountsArrived(LoadOperation<Account> lo)
{
    foreach (var account in lo.Entities.Where(acc => acc.IsRootAccount))
    {
        ParentAccounts.Add(account.Name);
    }
}   

这是要走的路吗?此更改是否存在性能问题?