模型重映射与Linq2SQL

模型重映射与Linq2SQL,linq,linq-to-sql,model,lambda,Linq,Linq To Sql,Model,Lambda,我正在尽最大努力创建一个模型映射器,通过Linq2SQL将任何表达式直接传递回SQL,到目前为止,我已经成功地将表达式树中的所有属性重新映射回原始模型。我遇到的问题是,每当我尝试将表达式树与Linq2SQL一起使用时,它都会失败,并出现以下错误: 参数“modelParamName”未绑定在指定的LINQ to Entities查询表达式中 下面是表达式重新映射器的代码-其中有很多扩展函数: // Converting all members from using TModel to TElem

我正在尽最大努力创建一个模型映射器,通过Linq2SQL将任何表达式直接传递回SQL,到目前为止,我已经成功地将表达式树中的所有属性重新映射回原始模型。我遇到的问题是,每当我尝试将表达式树与Linq2SQL一起使用时,它都会失败,并出现以下错误:

参数“modelParamName”未绑定在指定的LINQ to Entities查询表达式中

下面是表达式重新映射器的代码-其中有很多扩展函数:

// Converting all members from using TModel to TElement
internal class ExpressionModifier<TModel, TElement> : ExpressionVisitor {

    #region Members

    #region Constructors

    internal ExpressionModifier(IQueryable source) { this.source = source; }

    #endregion

    #region Variables

    private IQueryable source;

    #endregion

    #region Methods

    internal Expression Modify(Expression expression) { var result = this.Visit(expression); return result; }

    protected override Expression VisitParameter(ParameterExpression node) {
        if(node.Type == typeof(TModel)) { return Expression.Parameter(typeof(TElement), node.Name); }
        return base.VisitParameter(node);
    }

    protected override Expression VisitConstant(ConstantExpression node) {
        if(node.Value is IQueryable) { return Expression.Constant(this.source); }
        return base.VisitConstant(node);
    }

    protected override Expression VisitMethodCall(MethodCallExpression node) {
        var arguments = node.Arguments.Select(arg => this.Visit(arg));
        var genericTypes = node.Method.GetGenericArguments().Select(arg=>this.VisitParameter(Expression.Parameter(arg)).Type);
        var newMethod = typeof(Queryable).GetMethods().SingleOrDefault(method => method.MetadataToken == node.Method.MetadataToken);
        return Expression.Call(newMethod.MakeGenericMethod(genericTypes.ToArray()), arguments);         
    }

    protected override Expression VisitLambda<T>(Expression<T> node) {
        var body = this.Visit(node.Body);
        var parameters = node.Parameters.Select(parameter => this.VisitParameter(parameter) as ParameterExpression);
        return Expression.Lambda(body, parameters.ToArray());
    }

    protected override Expression VisitMember(MemberExpression node) {
        var memberName = node.Member.Name;
        var modelAttribute = node.Member.GetAllAttributes().OfType<ModelAttribute>().SingleOrDefault();
        if(modelAttribute != null && modelAttribute.Name.IsNotNull()) { memberName = modelAttribute.Name; }
        var newMember = typeof(TElement).GetAllProperties().SingleOrDefault(property => property.Name == memberName);
        if(newMember != null) { return Expression.MakeMemberAccess(Visit(node.Expression), newMember); }
        return base.VisitMember(node);
    }

    #endregion

    #endregion

}

如果有人能帮我找出我做错了什么,我将不胜感激。

最终找出了我做错了什么;但这并不是我所期望的。在对可以按原样传递的查询使用消除过程后,我删除了所有的访问方法。然而,这是有效的,表达式与我所有的访问方法完全相同,但当添加回查询时,查询不起作用

在我添加回VisitParameter方法后,它最终发现它停止了工作。过了一段时间,我意识到从Expression.Parameter创建一个新的ParameterExpression实例是一个问题,即使使用相同的名称,如果它在相关的表达式块或范围内多次出现。即使它具有相同的名称,但在实例化时,它在技术上代表了一个完全不同的参数

例如:

param => param + 1
如果在这里使用Expression.Parameternode和param两次,则每个实例都是完全不同的变量。这是故意的吗?在同一范围内的表达式树中具有相同类型和名称的参数一定是同一个变量吗

我解决这个问题的唯一方法是创建一个类型为string和ParameterExpression的字典,因此如果再次出现相同的命名参数,我将使用以前创建的参数实例

我现在只需要弄清楚如何使这本字典中的参数只适用于它们自己的作用域——啊,好吧,如果太简单的话,我可能会感到厌烦