【发布时间】:2017-03-31 11:10:18
【问题描述】:
我正在尝试根据给定的配置动态构建一些 sql 查询,以仅查询所需的数据:
当编写普通的 linq 时,它看起来像这样:
var data = dbContext
.TableOne
.Select(t1 => new TableOneSelect
{
TableOneId = t1.TableOneId,
TableOneTableTwoReference = new[] { TableOne.FirstTableTwoReference.Invoke(t1) }
.Select(t2 => new TableTwoSelect
{
TableTowId = (Guid?)t2.TableTwoId,
// ... some more properties of t2
}).FirstOrDefault(),
// ... some more properties of t1
});
而 TableOne.FirstTableTwoReference.Invoke(t1) 已定义
public static Expression<Func<TableOne, TableTwo>> FirstTableTwoReference => (t1) => t1.TableTwoReferences.FirstOrDefault();
目前我有以下动态构建 TableOne 部分:
public Expression<Func<TableOne, TableOneSelect>> Init(TableOneConfig cfg)
{
var memberBindings = new List<MemberBinding>();
var selectType = typeof(TableOneSelect);
var newExpression = Expression.New(selectType);
var theEntity = Expression.Parameter(typeof(TableOne), "t1");
// decide if the property is needed and add to the object-initializer
if (cfg.Select("TableOneId"))
memberBindings.Add(Expression.Bind(selectType.GetProperty("TableOneId"), Expression.Property(theEntity, nameof("TableOneId"))));
// ... check other properties of TableOneSelect depending on given config
var memberInit = Expression.MemberInit(newExpression, memberBindings);
return Expression.Lambda<Func<tblTournament, EventResourceSelect>>(memberInit, theEntity);
}
TableTwo 相同(不同的属性和不同的数据库表)。
这个我可以像这样动态调用
dbContext.TableOne.Select(t => TableOneHelper.Init(cfg).Invoke(t1));
而Invoke 是来自LinqKit 的那个。
但我被TableOneTableTwoReference 的内部部分卡住了,我需要在其中进行枚举以调用TableTwoHelper 的Init,但我不明白如何实现这一点。
我猜Expression.NewArrayInit(typeof(TableTwo), ...) 将是第一步。但是我仍然被困在如何将t1.TableTwoReferences.FirstOrDefault() 传递给这个调用Select 的数组。
【问题讨论】:
-
记住
x.FirstOrDefault()等同于Enumerable.FirstOrDefault(x)可能对您有所帮助。然后你可以使用Expression.Call()。 -
@vyrp 我真正的问题更复杂,因为第一个
FirstOrDefault()也是Expression<Func<TableOne, TableTwo>>,我需要调用它来填充数组。将更新我的问题
标签: c# linq expression expression-trees