我有一个类似的查询:
from joinedEntity in joinedEntities
join relatedEntity in dbContext.X on ....
现在,我想以" X"的方式编写上述查询。可以动态传递,这样我就不需要为每个不同的" X"编写单独的linq查询。有帮助吗?我应该使用表达树和反射吗?如果有,怎么样?谢谢。
我猜想它应该是这样的:
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
};
答案 0 :(得分:1)
最简单的方法是创建一个表示存在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。实体框架的所有类都是部分的,因此您只需要创建另一个部分类来添加此接口。
由于您希望投影只是创建一个扩展方法,我们将链接到标准连接。
public static class CustomIQueryableExtensions
{
public static IQueryable<TResult> CommonJoinQueryable<TOuter, TInner, TResult>(this IQueryable<TOuter> outer,
IQueryable<TInner> inner,
Expression<Func<TOuter, TInner, TResult>>
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<Func<TOuter, int>>(Expression.Property(outerParam, "CId"), outerParam);
var innerParam = Expression.Parameter(typeof (TInner), "inner");
var innerBody = Expression.Lambda<Func<TInner, int>>(Expression.Property(innerParam, "Id"), innerParam);
return outer.Join(inner, outerBody, innerBody, resultSelector);
}
public static IEnumerable<TResult> CommonJoinEnumerable<TOuter, TInner, TResult>(this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TInner, TResult>
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<TOuter, int> outerJoin = outerParam => outerParam.Id;
Func<TInner, int> 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试图得到的。