在内蒙古选择左表加入到DbScanExpression在实体框架拦截(Selecting Left

2019-11-03 18:05发布

继SO回答过的问题在这里 ,我想选择所有在右表中的列的唯一,而不必明确与左表中的用户ID一起指定列名。

这是如何的任何想法可以做什么?

 public override DbExpression Visit(DbScanExpression expression) { var table = expression.Target.ElementType as EntityType; if (table != null && table.Name == "User") { return expression.InnerJoin( DbExpressionBuilder.Scan(expression.Target.EntityContainer.BaseEntitySets.Single(s => s.Name == "TennantUser")), (l, r) => DbExpressionBuilder.Equal( DbExpressionBuilder.Property(l, "UserId"), DbExpressionBuilder.Property(r, "UserId") ) ) .Select(exp => new { UserId = exp.Property("l").Property("UserId"), Email = exp.Property("l").Property("Email") }); } return base.Visit(expression); } 

Answer 1:

也许答案是有点晚了,但无论如何,它可以帮助别人节省时间

 public override DbExpression Visit(DbScanExpression expression)
    {
        var table = expression.Target.ElementType as EntityType;

        if (table != null && table.Name == "User")
        {
            var rightExpression = expression.Target.EntityContainer.GetEntitySetByName("TennantUser", true).Scan();

            var join = expression.InnerJoin(rightExpression,
                (l, r) =>
                        DbExpressionBuilder.Equal(
                            DbExpressionBuilder.Property(l, "UserId"),
                            DbExpressionBuilder.Property(r, "UserId")
                        ));


            var select = join.Select(exp => DbExpressionBuilder.NewRow(
                expression.Target.ElementType.Members.Select(x => 
                    new KeyValuePair<string, DbExpression>(x.Name, exp.Property(join.Left.VariableName).Property(x.Name)))));


            return select;

        }

        return base.Visit(expression);
    }


Answer 2:

using LatticeUtils;
using System;
using System.Collections.Generic;
using System.Data.Entity.Core.Common.CommandTrees;
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Authorisation
{
  public static class DbPropertyExpressionProjector
  {
    /// <summary>
    /// Constructs an anonymous function that returns a DbExpression and expects an Anonymous Type.
    /// Supports the ability to dynamically create the following lambda:
    /// p => new {
    ///   Column1 = p.Property("l").Property("Column1")
    /// }
    /// </summary>
    /// <param name="fields">List of column names</param>
    /// <returns>Func<DbExpression,T></returns>
    public static LambdaExpression CreateLambdaExpression(Dictionary<string, string> fields)
    {
      Type type = Type.GetType("System.Func`2");

      Type[] anonymousTypeArguments = fields.Keys.Select(p => typeof(DbPropertyExpression)).ToArray();
      Type anonymousType = AnonymousTypeUtils.CreateGenericTypeDefinition(fields.Keys);
      anonymousType = anonymousType.MakeGenericType(anonymousTypeArguments);

      Type[] typeArguments = new[] { typeof(DbExpression), anonymousType };
      var lambdaType = type.MakeGenericType(typeArguments);

      var pParam = Expression.Parameter(typeof(DbExpression), "p");
      ParameterExpression[] parameters = { pParam };

      ConstructorInfo constructor = anonymousType.GetConstructors().SingleOrDefault();

      MethodInfo memberInfo = typeof(DbExpressionBuilder).GetMethods().FirstOrDefault(m => m.ToString() == "System.Data.Entity.Core.Common.CommandTrees.DbPropertyExpression Property(System.Data.Entity.Core.Common.CommandTrees.DbExpression, System.String)");

      List<Expression> argumentList = new List<Expression>();
      List<MemberInfo> membersList = new List<MemberInfo>();

      foreach (string field in fields.Keys)
      {
        Expression[] leftTableExpressions = { pParam, Expression.Constant(fields[field]) };
        Expression methodCallExpression = Expression.Call(null, memberInfo, leftTableExpressions);

        Expression[] secondPropertyExpressions = { methodCallExpression, Expression.Constant(field) };
        argumentList.Add(Expression.Call(null, memberInfo, secondPropertyExpressions));
        membersList.Add(anonymousType.GetMembers().FirstOrDefault(m => m.ToString() == string.Format("System.Data.Entity.Core.Common.CommandTrees.DbPropertyExpression {0}", field)));
      }

      var body = Expression.New(constructor, argumentList, membersList);

      return Expression.Lambda(lambdaType, body, parameters);
    }
  }
}


文章来源: Selecting Left Table on Inner Join to DbScanExpression in Entity Framework Interceptor