: 問題があります... コンパイル済みの DLL の代わりに NHibernate 3.3.3 ソースを使用することにしました。NHibernate の問題にうんざりしていて、それらをデバッグできない (つまり、ブラック ボックス) からです。私は流暢なNHibernateで同じことをしました。
流暢な NHibernate 用にコンパイルしたソースを、コンパイル済みの NHibernate DLL でテストしたところ、動作しました。そこで、さらに進んで NHibernate でも同じことを行うことにしました。これが悪いところです:私のアプリの起動、検索エンジンのボークなど...しかし、何かを保存しようとするたびに、受信時にクラスHqlTreeNodeExtensions(ファイルHQLTreeNode.cs内)の「AsBooleanExpression」メソッドでInvalidCastExceptionを取得しますタイプ「NHibernate.Hql.Ast.HQLBitWiseAnd」の値で、NHibernate.Hql.Ast.HqlBooleanExpression としてキャストできません。
コンパイルされた DLL で動作し、ソースでは動作しないのはなぜですか? 私は NHibernate の内部についてはまったく知りませんが、私は VB 開発者であるため、c# については少し知っています。
これが起こる場所です:
public static class HqlTreeNodeExtensions
{
public static HqlExpression AsExpression(this HqlTreeNode node)
{
// TODO - nice error handling if cast fails
return (HqlExpression)node;
}
public static HqlBooleanExpression AsBooleanExpression(this HqlTreeNode node)
{
if (node is HqlDot)
{
return new HqlBooleanDot(node.Factory, (HqlDot) node);
}
// TODO - nice error handling if cast fails
return (HqlBooleanExpression)node; <-------- RIGHT HERE - the cast fails
}
}
(スタック呼び出しの画像を投稿できません。読み取り可能なテキストとして変換しようとします)
誰かが彼を助けることができますか?
どうもありがとう
ニコ
PS これが完全なコール スタックです。ここで、完全なコール スタックに進みます: 自分のコードからの抜粋: すべては、「Dim ctrlResultatsRecherche As New ResultatsRechercheClientV2...」という行から始まります。
Private Sub RechercheClient_KeyDown(ByVal sender As Object, ByVal e As KeyEventArgs) Handles txtCodePostal.KeyDown, txtClient.KeyDown, txtRue.KeyDown, txtVille.KeyDown
If e.KeyCode = Keys.Enter Then
Dim bolMaibecExpress As Boolean = False
'Récupérer le contrôle parent.
If Not Parent Is Nothing AndAlso TypeOf Parent.Parent Is SaisieDemandeEchantillon Then
bolMaibecExpress = TryCast(Parent.Parent, SaisieDemandeEchantillon).chkMaibecExpress.Checked
End If
panDetails.Controls.DisposeAndRemoveAll()
Dim ctrlResultatsRecherche As New ResultatsRechercheClientV2(m_Session, txtClient.Text, txtCodePostal.Text, txtVille.Text, txtRue.Text, bolMaibecExpress)
AddHandler ctrlResultatsRecherche.ClientSelectionneV2, AddressOf RésultatsRecherche_ClientSélectionné
panDetails.Controls.Add(ctrlResultatsRecherche)
panDetails.Visible = True
End If
End Sub
次に、自分のコードからの抜粋:「Dim resultats = m_Session.Query(Of Client).Where(predicat.Expand).ToList」という行で停止します
Public Sub New(ByVal session As ISession, ByVal strClient As String, ByVal strCodePostal As String, ByVal strVille As String, ByVal strRue As String, Optional ByVal MaibecExpress As Boolean = False)
' This call is required by the Windows Form Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
dgvResultatsRecherche.AutoGenerateColumns = False
m_Session = session
Dim predicat = PredicateBuilder.False(Of Client)()
predicat = predicat.Or(Function(x As Client) (x.Prenom.Contains(strClient) OrElse x.Nom.Contains(strClient) OrElse x.Telephone.Contains(strClient) OrElse x.Courriel.Contains(strClient) OrElse strClient = "") _
And (x.Adresse.CodePostal.Contains(strCodePostal) Or strCodePostal = "") _
And (x.Adresse.Ville.Contains(strVille) Or strVille = "") _
And (x.Adresse.Ligne1.Contains(strRue) Or strRue = "") _
And (x.MaibecExpress = MaibecExpress Or MaibecExpress = False))
Dim resultats = m_Session.Query(Of Client).Where(predicat.Expand).ToList
dgvResultatsRecherche.DataSource = resultats
lblNbResultatsTrouvés.Text = String.Format("{0} résultats trouvés", resultats.Count)
SetDataBindings()
End Sub
次に、remotion.link.dll への呼び出し -> Remotion.Linq.QueryableBase.GetEnumerator() (申し訳ありませんが、コードはありません)
次に、「NhLinqExpression nhLinqExpression = PrepareQuery(expression, out query, out nhQuery);」で、NHibernate.Linq.DefaultQueryProvider からサブを実行します。ライン
public TResult Execute<TResult>(Expression expression)
{
return (TResult) Execute(expression);
}
次に、「return」行で、NHibernate.Linq.DefaultQueryProvider から sub を実行します。
public virtual object Execute(Expression expression)
{
IQuery query;
NhLinqExpression nhQuery;
NhLinqExpression nhLinqExpression = PrepareQuery(expression, out query, out nhQuery);
return ExecuteQuery(nhLinqExpression, query, nhQuery);
}
次に、「query = Session.CreateQuery(nhLinqExpression);」で、NHibernate.Linq.DefaultQueryProvider から PrepareQuery を実行します。ライン
protected NhLinqExpression PrepareQuery(Expression expression, out IQuery query, out NhLinqExpression nhQuery)
{
var nhLinqExpression = new NhLinqExpression(expression, Session.Factory);
query = Session.CreateQuery(nhLinqExpression);
nhQuery = query.As<ExpressionQueryImpl>().QueryExpression.As<NhLinqExpression>();
SetParameters(query, nhLinqExpression.ParameterValuesByName);
SetResultTransformerAndAdditionalCriteria(query, nhQuery, nhLinqExpression.ParameterValuesByName);
return nhLinqExpression;
}
次に、「var queryPlan = GetHQLQueryPlan(queryExpression, false);」で、NHibernate.Impl.AbstractSessionImpl から CreateQuery サブルーチンを作成します。ライン
public virtual IQuery CreateQuery(IQueryExpression queryExpression)
{
using (new SessionIdLoggingContext(SessionId))
{
CheckAndUpdateSessionStatus();
var queryPlan = GetHQLQueryPlan(queryExpression, false);
var query = new ExpressionQueryImpl(queryPlan.QueryExpression,
this,
queryPlan.ParameterMetadata
);
query.SetComment("[expression]");
return query;
}
}
次に、NHibernate.Impl.AbstractSessionImpl からの GetHQLQueryPlan サブ (戻り行でジャム)
protected internal virtual IQueryExpressionPlan GetHQLQueryPlan(IQueryExpression queryExpression, bool shallow)
{
using (new SessionIdLoggingContext(SessionId))
{
return factory.QueryPlanCache.GetHQLQueryPlan(queryExpression, shallow, EnabledFilters);
}
}
次に、NHibernate.Engine.Query.QueryPlan から GetHQLQueryPlan サブ (行 Plan = new HQLExpressionQueryPlan (...) でジャム)
public IQueryExpressionPlan GetHQLQueryPlan(IQueryExpression queryExpression, bool shallow, IDictionary<string, IFilter> enabledFilters)
{
string expressionStr = queryExpression.Key;
var key = new HQLQueryPlanKey(queryExpression, shallow, enabledFilters);
var plan = (IQueryExpressionPlan)planCache[key];
if (plan == null)
{
if (log.IsDebugEnabled)
{
log.Debug("unable to locate HQL query plan in cache; generating (" + expressionStr + ")");
}
plan = new HQLExpressionQueryPlan(expressionStr, queryExpression, shallow, enabledFilters, factory);
planCache.Put(key, plan);
}
else
{
if (log.IsDebugEnabled)
{
log.Debug("located HQL query plan in cache (" + expressionStr + ")");
}
var planExpression = plan.QueryExpression as NhLinqExpression;
var expression = queryExpression as NhLinqExpression;
if (planExpression != null && expression != null)
{
//NH-3413
//Here we have to use original expression.
//In most cases NH do not translate expression in second time, but
// for cases when we have list parameters in query, like @p1.Contains(...),
// it does, and then it uses parameters from first try.
//TODO: cache only required parts of QueryExpression
planExpression._expression = expression._expression;
planExpression._constantToParameterMap = expression._constantToParameterMap;
}
}
return plan;
}
次に、HQLExpressionQueryPlan (プロパティをスキップ) で、戻り行で:
private static IQueryTranslator[] CreateTranslators(string expressionStr, IQueryExpression queryExpression, string collectionRole, bool shallow, IDictionary<string, IFilter> enabledFilters, ISessionFactoryImplementor factory)
{
IQueryTranslatorFactory2 qtFactory = new ASTQueryTranslatorFactory();
return qtFactory.CreateQueryTranslators(expressionStr, queryExpression, collectionRole, shallow, enabledFilters, factory);
}
次に、ASTQueryTranslatorFactory.cs の戻り行で:
public IQueryTranslator[] CreateQueryTranslators(string queryIdentifier, IQueryExpression queryExpression, string collectionRole, bool shallow, IDictionary<string, IFilter> filters, ISessionFactoryImplementor factory)
{
return CreateQueryTranslators(queryExpression.Translate(factory), queryIdentifier, collectionRole, shallow,
filters, factory);
}
QueryModelVisitor.cs の GenerateHqlQuery (抜粋のみ) の Visitor.Visit() 行 //... // クエリ ソースを識別して名前を付ける QuerySourceIdentifier.Visit(parameters.QuerySourceNamer, queryModel);
var visitor = new QueryModelVisitor(parameters, root, queryModel) { RewrittenOperatorResult = result };
visitor.Visit();
return visitor._hqlTree.GetTranslation();
次に、コードを持っていない Remotion DLL を 2 回呼び出します...そして、QueryModelVisitor.cs の VisitWhereClause の var expression =... 行で...
public override void VisitWhereClause(WhereClause whereClause, QueryModel queryModel, int index)
{
// Visit the predicate to build the query
var expression = HqlGeneratorExpressionTreeVisitor.Visit(whereClause.Predicate, VisitorParameters).AsBooleanExpression();
if (whereClause is NhHavingClause)
{
_hqlTree.AddHavingClause(expression);
}
else
{
_hqlTree.AddWhereClause(expression);
}
}
次に、HQLGeneratorExpressionTreeVisitor.cs の visit 関数で、改行します。
public static HqlTreeNode Visit(Expression expression, VisitorParameters parameters)
{
return new HqlGeneratorExpressionTreeVisitor(parameters).VisitExpression(expression);
}
次に、同じファイルで、改行 VisitBinaryExpression((BinaryExpression) 式) - (抜粋のみ):
//...
case ExpressionType.GreaterThan:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
case ExpressionType.Coalesce:
case ExpressionType.ArrayIndex:
return VisitBinaryExpression((BinaryExpression) expression);
case ExpressionType.Conditional:
return VisitConditionalExpression((ConditionalExpression) expression);
case ExpressionType.Constant:
return VisitConstantExpression((ConstantExpression) expression);
//...
同じファイル、関数 VisitBinaryExpression、linereturn _hqlTreeBuilder.BooleanOr(lhs.AsBooleanExpression()、rhs.AsBooleanExpression()) - 抜粋のみ
//...
case ExpressionType.AndAlso:
return _hqlTreeBuilder.BooleanAnd(lhs.AsBooleanExpression(), rhs.AsBooleanExpression());
case ExpressionType.Or:
return _hqlTreeBuilder.BitwiseOr(lhs, rhs);
case ExpressionType.OrElse:
return _hqlTreeBuilder.BooleanOr(lhs.AsBooleanExpression(), rhs.AsBooleanExpression());
case ExpressionType.Add:
if (expression.Left.Type == typeof (string) && expression.Right.Type == typeof (string))
{
return _hqlTreeBuilder.MethodCall("concat", lhs, rhs);
}
return _hqlTreeBuilder.Add(lhs, rhs);
//...
最後に、HQLTreeNode.cs の改行 (HqlBooleanExpression)node の奇妙な todo コメントの近く:
public static class HqlTreeNodeExtensions
{
public static HqlExpression AsExpression(this HqlTreeNode node)
{
// TODO - nice error handling if cast fails
return (HqlExpression)node;
}
public static HqlBooleanExpression AsBooleanExpression(this HqlTreeNode node)
{
if (node is HqlDot)
{
return new HqlBooleanDot(node.Factory, (HqlDot) node);
}
// TODO - nice error handling if cast fails
return (HqlBooleanExpression)node;
}
}