11using System . Linq . Expressions ;
2+ using NHibernate . Linq . Visitors ;
3+ using NHibernate . Proxy ;
4+ using NHibernate . Util ;
25
36namespace NHibernate . Linq
47{
@@ -12,7 +15,37 @@ internal static class LinqLogging
1215 internal static void LogExpression ( string msg , Expression expression )
1316 {
1417 if ( Log . IsDebugEnabled )
15- Log . DebugFormat ( "{0}: {1}" , msg , expression . ToString ( ) ) ;
18+ {
19+ // If the expression contains NHibernate proxies, those will be initialized
20+ // when we call ToString() on the exception. The string representation is
21+ // generated by a class internal to System.Linq.Expression, so we cannot
22+ // actually override that logic. Circumvent it by replacing such ConstantExpressions
23+ // with ParameterExpression, having their name set to the string we wish to display.
24+ var visitor = new ProxyReplacingExpressionTreeVisitor ( ) ;
25+ var preparedExpression = visitor . VisitExpression ( expression ) ;
26+
27+ Log . DebugFormat ( "{0}: {1}" , msg , preparedExpression . ToString ( ) ) ;
28+ }
29+ }
30+
31+
32+ /// <summary>
33+ /// Replace all occurances of ConstantExpression where the value is an NHibernate
34+ /// proxy with a ParameterExpression. The name of the parameter will be a string
35+ /// representing the proxied entity, without initializing it.
36+ /// </summary>
37+ private class ProxyReplacingExpressionTreeVisitor : NhExpressionTreeVisitor
38+ {
39+ // See also e.g. Remotion.Linq.Clauses.ExpressionTreeVisitors.FormattingExpressionTreeVisitor
40+ // for another example of this technique.
41+
42+ protected override Expression VisitConstantExpression ( ConstantExpression expression )
43+ {
44+ if ( expression . Value . IsProxy ( ) )
45+ return Expression . Parameter ( expression . Type , ObjectUtils . IdentityToString ( expression . Value ) ) ;
46+
47+ return base . VisitConstantExpression ( expression ) ;
48+ }
1649 }
1750 }
1851}
0 commit comments