动态设置要加入LINQ查询的实体

编程入门 行业动态 更新时间:2024-10-24 12:28:29
本文介绍了动态设置要加入LINQ查询的实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我有一个查询:

来自joinedEntities中的joinedEntity 在dbContext.X中加入relatedEntity .. ..

现在,我想以X动态的方式编写上述查询传递,所以我不需要为每个不同的X写一个单独的linq查询。任何帮助?我应该使用表达式树和反射?如果是,怎么样?谢谢。

我有一些猜测应该是这样的:

var parameter = Expression.Parameter(typeof(CompanyContext),dbContext); var member = Expression.MakeMemberAccess(parameter,typeof(CompanyContext).GetMember(X)[0]); .....

以下是我的加入示例:

来自joinedEntities中的joinedEntity joinEntity.Id的相关连接在dbContext.Channels中等于relatedEntity.CId 选择新的JoinedEntities( joinEntity) { Channel = relatedEntity.Name };

这是它的方法语法:

新的连接实体(m){(),(m,k)=> Channel = k.Name});

这也是另一个:

来自joinedEntity的joinEntities joinEntity.Id等于relatedEntity.CId 选择新的JoinedEntities(joinedEntity) { ActivityOutput = relatedEntity.Name };

解决方案

最简单的方法是创建一个界面有一个CId字段。

//不知道你是否需要这个,或者如果你想要joinEntities总是一样的 public interface IJoinedEntities { int Id {get;组; } } public interface IRelatedEntity { int CId {get;组; } }

所有相关实体都需要实现IRelatedEntity。实体框架的所有类都是部分的,所以你只需要做另外一个局部类来添加这个接口。

由于你希望投影只是创建一个扩展方法,将链接到标准连接。

public static class CustomIQueryableExtensions { public static IQueryable< TResult> CommonJoinQueryable 现在你可以使用它,仍然处理投影

joinedEntities.CommonJoinQueryable(dbContext.Channels,(m,k)=> new JoinedEntities(){Channel = Name,tracking = m}); joinedEntities.CommonJoinEnumerable(dbContext.Channels,(m,k)=> new JoinedEntities(m){Channel = k.Name});

您还应该使用SQL Profiler来观察当您使用Enumerable时生成的内容,因为它将结果拉下来,然后将它们加入到内存中,而不是从SQL中加入。我知道这是你要求的,但这不常见。不要将参数传递给构造函数,您应该考虑使用可以使用投影设置的属性,然后使用IQueryable。

我相信这是什么lnanikian试图得到。

I have a query like :

from joinedEntity in joinedEntities join relatedEntity in dbContext.X on ....

Now, I want to write the above query in a way that "X" could be dynamically passed so that I don't need to write a separate linq query for every different "X". Any help? Should I use expression trees and reflections? If yes, how? Thank you.

I have some guess that it should be something like this:

var parameter = Expression.Parameter(typeof (CompanyContext), "dbContext"); var member = Expression.MakeMemberAccess(parameter, typeof(CompanyContext).GetMember("X")[0]); .....

Here is a sample of my Join:

from joinedEntity in joinedEntities join relatedEntity in dbContext.Channels on joinedEntity.Id equals relatedEntity.CId select new JoinedEntities(joinedEntity) { Channel = relatedEntity.Name };

And this is the method syntax of it:

joinedEntities.Join(dbContext.Channels, m => m.Id, k => k.CId, (m, k) => new JoinedEntities(m) { Channel = k.Name });

This is also another one:

from joinedEntity in joinedEntities join relatedEntity in dbContext.ActivityOutput on joinedEntity.Id equals relatedEntity.CId select new JoinedEntities(joinedEntity) { ActivityOutput = relatedEntity.Name };

解决方案

The easiest way would be to create an interface that says there is an CId field.

// 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; } }

All the related entities would need to implement IRelatedEntity. Entity Framework has all their class are partial so you would just need to make another partial class to add this interface.

Since you want the projections just create an extension method that we will chain into the standard join.

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); } }

Now you can just use it and still handle the projection.

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 });

You should still use SQL Profiler to watch what gets generated when you use the Enumerable because it will pull the results down and then join them in memory, not from SQL. I know that's what you requested but it's not common. Instead of passing a parameter into the constructor you should consider making a property that you can just set with the projection then stick with IQueryable.

I believe this is what lnanikian was trying to get at.

更多推荐

动态设置要加入LINQ查询的实体

本文发布于:2023-06-03 10:04:20,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/473745.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:实体   动态   LINQ

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!