访问基于方法的体现成员来构建表达式树

时间:2019-02-27 05:05:16

标签: c# .net linq-to-sql expression-trees

尝试使用表达式树通过表达式构建订单。但是我无法访问查询结果的类的表达式主体属性。 这是类结构:

public class AssetFileRecord : IAuditable, IEntity, INavigateToCustomValues
{
    public AssetFileRecord()
    {
        this.UpdatedTimeStamp = DateTime.UtcNow;
    }

    public AssetFileRecord GetRecord()
    {
        return this;
    }

    public Guid Id { get; set; }
    public int DisplayId { get; set; }
    public string AssetTagNumber { get; set; }
    [JObjectIgnore]
    public virtual Account Account { get; set; }
    public string AccountNumber => Account?.AccountNumber;
    public string AuditTrail { get; set; }
    public string OldTagNumber { get; set; }
    public ActivityCode ActivityCode { get; set; }

    [JObjectIgnore]
    public virtual ICollection<AssetFileRecordDepreciation> AssetFileRecordDepreciations { get; set; }
    // Depreciation Records
    public double? AccumulatedDepreciation => Depreciation()?.AccumulatedDepreciation;
    public DateTime? DepreciationAsOfDate => Depreciation()?.DepreciationAsOfDate;
    public double? LifeMonths => Depreciation()?.LifeMonths;
    public double? DepreciationBasis => Depreciation()?.DepreciationBasis;
    public double? PeriodDepreciation => Depreciation()?.PeriodDepreciation;

    private AssetFileRecordDepreciation Depreciation()
    {
        return AssetFileRecordDepreciations?.AsQueryable()?.OrderBy(d => d.AssetFileDepreciationBook.BookNo)?.FirstOrDefault();
    }
}

我无法访问属性AccumulatedDepreciation,它是AssetFileRecord虚拟属性的属性。

以下是当前代码,该代码对于任何其他非表达主体属性都适用。

    public static IQueryable<T> BuildOrderByExpression<T>(IQueryable<T> source, string sortProperty, ListSortDirection sortOrder, bool isFirstOrderTerm = true)
    {
        var type = typeof(T);
        var property = type.GetProperty(sortProperty, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
        var parameter = Expression.Parameter(type, "p");
        // ReSharper disable once AssignNullToNotNullAttribute
        Expression orderByExp;
        var map = AssetFileRecordExpressionHelper.GetExpressionEmbodiedMemberMappings();
        if (!map.TryGetValue($"{type.Name}.{property.Name}", out orderByExp))
        {
            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
            orderByExp = Expression.Lambda(propertyAccess, parameter);
        }
        var typeArguments = new[] { type, property.PropertyType };
        var methodBase = isFirstOrderTerm ? "OrderBy" : "ThenBy";
        var methodName = sortOrder == ListSortDirection.Ascending ? methodBase : $"{methodBase}Descending";
        var resultExp = Expression.Call(typeof(Queryable), methodName, typeArguments, source.Expression, Expression.Quote(orderByExp));

        return source.Provider.CreateQuery<T>(resultExp);
    }

在上面的代码“ map”中,是一个字典,该字典返回除Depreciation()顶部访问的成员以外的具体成员的适当表达术语。

public static Dictionary<string, Expression> GetExpressionEmbodiedMemberMappings()
        {
            var map = new Dictionary<string, Expression>
                {
                    {
                        $"{nameof(AssetFileRecord)}.{nameof(AssetFileRecord.AccountNumber)}",
                        (Expression<Func<AssetFileRecord, string>>) (
                            afr => afr.Account != null ? afr.Account.AccountNumber : null
                        )
                    }
                };
            return map;
        }

Expression.Call不会评估为有效的SQL查询,而是会引发异常。

 ((System.Data.Entity.Infrastructure.DbQuery<AssetFileRecord>)records).Sql = '((System.Data.Entity.Infrastructure.DbQuery<AssetFileRecord>)records).Sql' threw an exception of type 'System.NotSupportedException'

预期结果:应将按表达式的顺序附加到最后生成的表达式树中;尝试通过表达式属性属性成员进行排序时,这样做会失败。

有人可以帮我解决这个问题。

0 个答案:

没有答案