我正在将我的业务对象上的Linq查询映射到我的Entity Framework数据库。有没有其他人走这条路 - 或者更重要的是,是否有更好的方法来解决这个问题。
我想要实现的是能够从我的UI层对我的业务层运行简单查询,而无需向管理器(BL层)或存储库(DA层)添加其他方法
我得到的好处是我可以在UI层中描述我想要的投影,并且不需要在我的经理中创建单独的类或特殊方法,或者在我的DA层中进行额外的编码以有效地执行查询(在这种情况下是键+聚合数据)
var promoSource = new Queryable<BL.Promo>(new PromoQueryProvider());//When executed, Maps a BL Promo code query to an EF.PromoCode query
var query = from x in promoSource
where x.PromoCode != null && x.OrderDate >= startDate && x.OrderDate <= endDate
group x by x.PromoCode
into result
select new
{
PromoCode = result.Key.Trim(),
AverageOrderValue = result.Average(x => x.OrderSubtotal),
NumberOfOrders = result.Count()
};
var results = query.ToList(); //Executes the query in the data layer and passes back the projected data
promosDataView.DataSource = results;
promosDataView.DataBind();
以前我需要添加一个类来表示视图对象,Manager中的一个方法可以从实体构建摘要数据,或将调用转发到数据层以获取来自数据库的数据。
似乎工作正常,在有限的情况下,但我也觉得我在适当的分离方面错过了这条船 - 在电子商务应用程序中,为了简单的报告方案,我是否会过度使用maintaning分离层?如果我在aspx页面上使用EF数据源,我不会得到同样的好处吗?
答案 0 :(得分:0)
我已经开始沿着这条道路前进并取得了一些初步的成功。对我而言,关键是将引用A.MemberOfA
的表达式的一部分转换为引用B.MemberOfB
的表达式。例如,假设您有一个业务对象A
:
class A { public bool Selected { get; set; } }
和数据对象(实体)B
:
class B { public int SelectedInd { get; set; } }
如您所见,在数据库中,B
的选定状态由指标int
定义。如果您想获得所有选定的A
,您可能有一个谓词:
Expression<Func<A, bool>> aPredicate = a => a.Selected;
现在您需要在实体集上执行该谓词。如果B
:
SelectedInd > 0
您的商家规则
Expression<Func<B, bool>> bPredicate = b => b.SelectedInd > 0;
对我而言,诀窍是ExpressionVisitor类。通过扩展此类并覆盖Visit
方法,您可以使用对A
和A.Selected
的引用替换引用B
和B.SelectedInd > 0
的部分:
class ExpressionTranslator : ExpressionVisitor
{
public Expression<Func<B, bool>> TranslatePredicate(Expression<Func<A, bool>> predicate)
{
return (Expression<Func<B, bool>>)this.Visit(predicate);
}
public override Expression Visit(Expression exp)
{
if (exp is Expression<Func<A, bool>>)
{
Expression<Func<A, bool>> predicate = (Expression<Func<A, bool>>)exp;
Expression body = this.Visit(predicate.Body);
ParameterExpression parameter = (ParameterExpression)this.Visit(predicate.Parameters[0]);
return Expression.Lambda<Func<B, bool>>(body, parameter);
}
else if (exp is ParameterExpression)
{
ParameterExpression param = (ParameterExpression)exp;
if (param.Type == typeof(A))
return bPredicate.Parameters[0];
}
else if (exp is MemberExpression)
{
MemberExpression mbrExpr = (MemberExpression)exp;
if (mbrExpr.Member == typeof(A).GetProperty("Selected"))
return this.Visit(bPredicate.Body);
}
else
return base.Visit(exp);
}
}
当然,您可以想象使这种逻辑更通用。在我自己的实现中,我注册对象映射选择器,以便ExpressionTranslator.Visit
根据exp
动态选择要返回的表达式。
希望这有帮助。