私は、Linq2SQLを介して式を直接SQLに戻すモデルマッパーを作成するために最善を尽くしています。これまでのところ、式ツリーのすべてのプロパティを元のモデルに再マップすることができました。私が得ている問題は、Linq2SQLで式ツリーを使用しようとすると、次のエラーで失敗することです。
「パラメーター'modelParamName'は、指定されたLINQtoEntitiesクエリ式にバインドされていませんでした。」
私のコードは以下のとおりです(式re-mapperの場合-その中にはかなりの数の拡張関数があります):
// 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
}
私が間違っている可能性があることを特定する助けをいただければ幸いです。