NHibernate和MySQL Nullable对象必须有一个值

NHibernate和MySQL Nullable对象必须有一个值,mysql,nhibernate,Mysql,Nhibernate,我遇到了一个问题,我希望得到一些关于从哪里开始的指导。让我先来设定场景 我最近从SQL Server迁移到了MySQl数据库,所有针对SQL Server的集成测试都通过了,现在有一个测试失败,因为迁移发生了以下异常: NHibernate.Exceptions.GenericADOException : could not execute query [ select post0_.Id as Id1_, post0_.CreatedAt as CreatedAt1_, post0_.Titl

我遇到了一个问题,我希望得到一些关于从哪里开始的指导。让我先来设定场景

我最近从SQL Server迁移到了MySQl数据库,所有针对SQL Server的集成测试都通过了,现在有一个测试失败,因为迁移发生了以下异常:

NHibernate.Exceptions.GenericADOException : could not execute query
[ select post0_.Id as Id1_, post0_.CreatedAt as CreatedAt1_, post0_.Title as Title1_, post0_.Body as Body1_, post0_.CreatedBy as CreatedBy1_, post0_.ParentId as ParentId1_ from Posts post0_, Users user1_ where post0_.CreatedBy=user1_.Id and ((user1_.Username is null) and (? is null) or user1_.Username=?) and (post0_.ParentId is null) order by post0_.CreatedAt desc ]
  Name:p1 - Value:username1
[SQL: select post0_.Id as Id1_, post0_.CreatedAt as CreatedAt1_, post0_.Title as Title1_, post0_.Body as Body1_, post0_.CreatedBy as CreatedBy1_, post0_.ParentId as ParentId1_ from Posts post0_, Users user1_ where post0_.CreatedBy=user1_.Id and ((user1_.Username is null) and (? is null) or user1_.Username=?) and (post0_.ParentId is null) order by post0_.CreatedAt desc]
  ----> System.InvalidOperationException : Nullable object must have a value

我将NHibernate v3与POCO模型和手工编制的SQL一起使用(使用DBDeploy.NET管理数据库版本控制)

在将模式创建SQL从SQL Server转换为MySQL时,我很可能犯了一个错误,但让我困惑的是,即使查询没有记录,我也会出现这个错误

为什么NHibernate试图创建任何对象?我对它的工作原理有什么不了解

这是其中一个查询的示例。这在返回行时引发了异常。根据设计,唯一返回null的列是Post.ParentId列

return GetSession()
    .Query<Post>()
    .Where(p => p.CreatedBy.Username == username && p.Parent == null)
    .OrderByDescending(p => p.CreatedAt)
    .Take(count)
    .ToList();

感谢毛里西奥让我回到堆栈跟踪。这似乎是GetLimitString()的MySQL5方言实现的一个问题。将方言从mysql5dialent更改为mysqldialent似乎可以解决这个问题

虽然,也许我很累,但当我看代码时,MySQL版本似乎包含了这种异常的风险,而不是MySQL5版本

mysqldial

public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit, int? offsetParameterIndex, int? limitParameterIndex)
        {
            var pagingBuilder = new SqlStringBuilder();
            pagingBuilder.Add(querySqlString);
            pagingBuilder.Add(" limit ");

            if (offset > 0)
            {
                pagingBuilder.Add(Parameter.WithIndex(offsetParameterIndex.Value));
                pagingBuilder.Add(", ");
            }

            pagingBuilder.Add(Parameter.WithIndex(limitParameterIndex.Value));

            return pagingBuilder.ToSqlString();
        }
public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit)
        {
            var pagingBuilder = new SqlStringBuilder();

            pagingBuilder.Add(querySqlString);
            pagingBuilder.Add(" limit ");
            if (offset > 0)
            {
                pagingBuilder.Add(offset.ToString());
                pagingBuilder.Add(", ");
            }

            pagingBuilder.Add(limit.ToString());

            return pagingBuilder.ToSqlString();
        }
mysql5方言

public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit, int? offsetParameterIndex, int? limitParameterIndex)
        {
            var pagingBuilder = new SqlStringBuilder();
            pagingBuilder.Add(querySqlString);
            pagingBuilder.Add(" limit ");

            if (offset > 0)
            {
                pagingBuilder.Add(Parameter.WithIndex(offsetParameterIndex.Value));
                pagingBuilder.Add(", ");
            }

            pagingBuilder.Add(Parameter.WithIndex(limitParameterIndex.Value));

            return pagingBuilder.ToSqlString();
        }
public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit)
        {
            var pagingBuilder = new SqlStringBuilder();

            pagingBuilder.Add(querySqlString);
            pagingBuilder.Add(" limit ");
            if (offset > 0)
            {
                pagingBuilder.Add(offset.ToString());
                pagingBuilder.Add(", ");
            }

            pagingBuilder.Add(limit.ToString());

            return pagingBuilder.ToSqlString();
        }

你能缩小范围,把问题缩短一点吗?另外,请发布异常堆栈跟踪。我正在努力缩小它的范围,寻找真正从哪里开始的指针。已附加完整输出。我觉得奇怪的是,当查询没有返回结果时,我在应用程序的另一个部分中遇到了这个错误。如果没有实例,为什么要尝试分配?
NHibernate.Cfg.SettingsFactory:  2010-12-18 15:56:20,159 INFO Default entity-mode: Poco
NHibernate.Cfg.SettingsFactory:  2010-12-18 15:56:20,160 INFO Named query checking : enabled
NHibernate.Impl.SessionFactoryImpl:  2010-12-18 15:56:20,211 INFO building session factory
NHibernate.Impl.SessionFactoryObjectFactory:  2010-12-18 15:56:20,580 INFO no name configured
NHibernate.Hql.Ast.ANTLR.Tree.FromElement:  2010-12-18 15:56:21,389 INFO handling property dereference [clubrd.service.Post (p) -> CreatedBy (Class)]
NHibernate.Hql.Ast.ANTLR.Tree.FromElement:  2010-12-18 15:56:21,406 INFO handling property dereference [clubrd.service.User () -> Username (Class)]
NHibernate.Hql.Ast.ANTLR.Tree.FromElement:  2010-12-18 15:56:21,416 INFO handling property dereference [clubrd.service.Post (p) -> CreatedBy (Class)]
NHibernate.Hql.Ast.ANTLR.Tree.FromElement:  2010-12-18 15:56:21,417 INFO handling property dereference [clubrd.service.User () -> Username (Class)]
NHibernate.Hql.Ast.ANTLR.Tree.FromElement:  2010-12-18 15:56:21,419 INFO handling property dereference [clubrd.service.Post (p) -> Parent (Class)]
NHibernate.Hql.Ast.ANTLR.Tree.FromElement:  2010-12-18 15:56:21,424 INFO handling property dereference [clubrd.service.Post (p) -> CreatedAt (Class)]
NHibernate.Util.ADOExceptionReporter:  2010-12-18 15:56:21,564 WARN System.InvalidOperationException: Nullable object must have a value.
   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Nullable`1.get_Value()
   at NHibernate.Dialect.MySQLDialect.GetLimitString(SqlString querySqlString, Int32 offset, Int32 limit, Nullable`1 offsetParameterIndex, Nullable`1 limitParameterIndex) in d:\CSharp\NH\nhibernate\src\NHibernate\Dialect\MySQLDialect.cs:line 197
   at NHibernate.Loader.Loader.PrepareQueryCommand(QueryParameters queryParameters, Boolean scroll, ISessionImplementor session) in d:\CSharp\NH\nhibernate\src\NHibernate\Loader\Loader.cs:line 1119
   at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in d:\CSharp\NH\nhibernate\src\NHibernate\Loader\Loader.cs:line 399
   at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in d:\CSharp\NH\nhibernate\src\NHibernate\Loader\Loader.cs:line 236
   at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) in d:\CSharp\NH\nhibernate\src\NHibernate\Loader\Loader.cs:line 1665
NHibernate.Util.ADOExceptionReporter:  2010-12-18 15:56:21,576 ERROR Nullable object must have a value.
NHibernate.Util.ADOExceptionReporter:  2010-12-18 15:56:21,577 WARN System.InvalidOperationException: Nullable object must have a value.
   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Nullable`1.get_Value()
   at NHibernate.Dialect.MySQLDialect.GetLimitString(SqlString querySqlString, Int32 offset, Int32 limit, Nullable`1 offsetParameterIndex, Nullable`1 limitParameterIndex) in d:\CSharp\NH\nhibernate\src\NHibernate\Dialect\MySQLDialect.cs:line 197
   at NHibernate.Loader.Loader.PrepareQueryCommand(QueryParameters queryParameters, Boolean scroll, ISessionImplementor session) in d:\CSharp\NH\nhibernate\src\NHibernate\Loader\Loader.cs:line 1119
   at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in d:\CSharp\NH\nhibernate\src\NHibernate\Loader\Loader.cs:line 399
   at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) in d:\CSharp\NH\nhibernate\src\NHibernate\Loader\Loader.cs:line 236
   at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) in d:\CSharp\NH\nhibernate\src\NHibernate\Loader\Loader.cs:line 1665
NHibernate.Util.ADOExceptionReporter:  2010-12-18 15:56:21,579 ERROR Nullable object must have a value.

NHibernate.Exceptions.GenericADOException : could not execute query
[ select post0_.Id as Id1_, post0_.CreatedAt as CreatedAt1_, post0_.Title as Title1_, post0_.Body as Body1_, post0_.CreatedBy as CreatedBy1_, post0_.ParentId as ParentId1_ from Posts post0_, Users user1_ where post0_.CreatedBy=user1_.Id and ((user1_.Username is null) and (? is null) or user1_.Username=?) and (post0_.ParentId is null) order by post0_.CreatedAt desc ]
  Name:p1 - Value:username1
[SQL: select post0_.Id as Id1_, post0_.CreatedAt as CreatedAt1_, post0_.Title as Title1_, post0_.Body as Body1_, post0_.CreatedBy as CreatedBy1_, post0_.ParentId as ParentId1_ from Posts post0_, Users user1_ where post0_.CreatedBy=user1_.Id and ((user1_.Username is null) and (? is null) or user1_.Username=?) and (post0_.ParentId is null) order by post0_.CreatedAt desc]
  ----> System.InvalidOperationException : Nullable object must have a value.
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) in d:\CSharp\NH\nhibernate\src\NHibernate\Loader\Loader.cs: line 1674
at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters) in d:\CSharp\NH\nhibernate\src\NHibernate\Loader\Loader.cs: line 1589
at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes) in d:\CSharp\NH\nhibernate\src\NHibernate\Loader\Loader.cs: line 1583
at NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters) in d:\CSharp\NH\nhibernate\src\NHibernate\Hql\Ast\ANTLR\Loader\QueryLoader.cs: line 298
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters) in d:\CSharp\NH\nhibernate\src\NHibernate\Hql\Ast\ANTLR\QueryTranslatorImpl.cs: line 110
at NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results) in d:\CSharp\NH\nhibernate\src\NHibernate\Engine\Query\HQLQueryPlan.cs: line 105
at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results) in d:\CSharp\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs: line 658
at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters parameters) in d:\CSharp\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs: line 634
at NHibernate.Impl.ExpressionQueryImpl.List() in d:\CSharp\NH\nhibernate\src\NHibernate\Impl\ExpressionQueryImpl.cs: line 63
at NHibernate.Linq.NhQueryProvider.ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery) in d:\CSharp\NH\nhibernate\src\NHibernate\Linq\NhQueryProvider.cs: line 78
at NHibernate.Linq.NhQueryProvider.Execute(Expression expression) in d:\CSharp\NH\nhibernate\src\NHibernate\Linq\NhQueryProvider.cs: line 27
at NHibernate.Linq.NhQueryProvider.Execute(Expression expression) in d:\CSharp\NH\nhibernate\src\NHibernate\Linq\NhQueryProvider.cs: line 102
at Remotion.Data.Linq.QueryableBase`1.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList(IEnumerable`1 source)
at clubrd.data.Repository.PostRepository.UsersLatestPosts(String username, Int32 count) in PostRepository.cs: line 13
at clubrd.data.integrationtest.Repository.PostRepositoryTests.UsersPosts() in PostRepositoryTests.cs: line 103
--InvalidOperationException
public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit, int? offsetParameterIndex, int? limitParameterIndex)
        {
            var pagingBuilder = new SqlStringBuilder();
            pagingBuilder.Add(querySqlString);
            pagingBuilder.Add(" limit ");

            if (offset > 0)
            {
                pagingBuilder.Add(Parameter.WithIndex(offsetParameterIndex.Value));
                pagingBuilder.Add(", ");
            }

            pagingBuilder.Add(Parameter.WithIndex(limitParameterIndex.Value));

            return pagingBuilder.ToSqlString();
        }
public override SqlString GetLimitString(SqlString querySqlString, int offset, int limit)
        {
            var pagingBuilder = new SqlStringBuilder();

            pagingBuilder.Add(querySqlString);
            pagingBuilder.Add(" limit ");
            if (offset > 0)
            {
                pagingBuilder.Add(offset.ToString());
                pagingBuilder.Add(", ");
            }

            pagingBuilder.Add(limit.ToString());

            return pagingBuilder.ToSqlString();
        }