动态设置要在LINQ查询中加入的实体
我有一个查询:
from joinedEntity in joinedEntities join relatedEntity in dbContext.X on ....
现在,我想以“X”可以动态传递的方式编写上述查询,这样我就不需要为每个不同的“X”编写单独的linq查询。 有帮助吗? 我应该使用表达树和reflection吗? 如果有,怎么样? 谢谢。
我有一些猜测它应该是这样的:
var parameter = Expression.Parameter(typeof (CompanyContext), "dbContext"); var member = Expression.MakeMemberAccess(parameter, typeof(CompanyContext).GetMember("X")[0]); .....
以下是我的加入示例:
from joinedEntity in joinedEntities join relatedEntity in dbContext.Channels on joinedEntity.Id equals relatedEntity.CId select new JoinedEntities(joinedEntity) { Channel = relatedEntity.Name };
这是它的方法语法:
joinedEntities.Join(dbContext.Channels, m => m.Id, k => k.CId, (m, k) => new JoinedEntities(m) { Channel = k.Name });
这也是另一个:
from joinedEntity in joinedEntities join relatedEntity in dbContext.ActivityOutput on joinedEntity.Id equals relatedEntity.CId select new JoinedEntities(joinedEntity) { ActivityOutput = relatedEntity.Name };
最简单的方法是创建一个表示存在CId字段的界面。
// Don't know if you need this one or if you want to have the class of joinedEntities always being the same public interface IJoinedEntities { int Id { get; set; } } public interface IRelatedEntity { int CId { get; set; } }
所有相关实体都需要实现IRelatedEntity。 entity framework的所有类都是部分的,因此您只需要创建另一个部分类来添加此接口。
由于您希望投影只是创建一个扩展方法,我们将链接到标准连接。
public static class CustomIQueryableExtensions { public static IQueryable CommonJoinQueryable(this IQueryable outer, IQueryable inner, Expression> resultSelector) where TOuter : IJoinedEntities where TInner : IRelatedEntity { // have to use expression trees to build the join otherwise cast to interface is in expression tree var outerParam = Expression.Parameter(typeof (TOuter), "outer"); var outerBody = Expression.Lambda>(Expression.Property(outerParam, "CId"), outerParam); var innerParam = Expression.Parameter(typeof (TInner), "inner"); var innerBody = Expression.Lambda>(Expression.Property(innerParam, "Id"), innerParam); return outer.Join(inner, outerBody, innerBody, resultSelector); } public static IEnumerable CommonJoinEnumerable(this IEnumerable outer, IEnumerable inner, Func resultSelector) where TOuter : IJoinedEntities where TInner : IRelatedEntity { // have to use expression trees to build the join otherwise cast to interface is in expression tree Func outerJoin = outerParam => outerParam.Id; Func relatedJoin = innerParam => innerParam.CId; return outer.Join(inner, outerJoin, relatedJoin, resultSelector); } }
现在你可以使用它并仍然处理投影。
joinedEntities.CommonJoinQueryable(dbContext.Channels, (m, k) => new JoinedEntities() { Channel = k.Name, tracking = m }); joinedEntities.CommonJoinEnumerable(dbContext.Channels, (m, k) => new JoinedEntities(m) { Channel = k.Name });
您仍然应该使用SQL事件探查器来查看使用Enumerable时生成的内容,因为它会将结果拉下来,然后将它们连接到内存中,而不是SQL中。 我知道这就是你的要求,但这并不常见。 您不应该将参数传递给构造函数,而应该考虑创建一个可以使用投影设置的属性,然后使用IQueryable。
我相信这是lnanikian试图得到的。