Я стараюсь изо всех сил попытаться создать модельный преобразователь, который проходит через любые выражения прямо к SQL через Linq2SQL, до сих пор мне удалось переназначить все свойства в дереве выражений обратно к оригиналу модель. Проблема, которую я получаю, заключается в том, что всякий раз, когда я пытаюсь использовать дерево выражений с Linq2SQL, он терпит неудачу с этой ошибкой:Модификация модели и 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
}
Любая помощь в определении того, что я мог бы делать неправильно была бы оценена.