2010-12-18 75 views
0

我遇到一個問題,我將不勝感激從哪裏開始的一些指導。讓我先設置一下場景。NHibernate和MySQL的可空對象必須有一個值

我最近從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(); 

地圖文件和類沒有改變,但已包括它們以供參考。

真的會歡迎任何想法,我應該在哪裏尋找。

郵政地圖

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="clubrd.service" namespace="clubrd.service"> 
    <class name="Post" table="Posts"> 
    <id name="Id"> 
     <generator class="guid.comb"/> 
    </id> 
    <property name="CreatedAt"/> 
    <property name="Title" column="Title"/> 
    <property name="Body"/> 
    <many-to-one name="CreatedBy" column="CreatedBy"/> 
    <many-to-one name="Parent" column="ParentId"/> 
    <set name="Children"> 
     <key column="ParentId"/> 
     <one-to-many class="Post"/> 
    </set> 
    </class> 
</hibernate-mapping> 

用戶的地圖,在這裏引用爲Post.CreatedBy

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="clubrd.service" namespace="clubrd.service"> 
    <class name="User" table="Users"> 
    <id name="Id"> 
     <generator class="guid.comb"/> 
    </id> 
    <property name="Username" not-null="true"/> 
    <property name="Email" not-null="true"/> 
    <property name="PasswordHash"/> 
    <property name="PasswordSalt"/> 
    <one-to-one name="Profile" class="Profile" /> 
    </class> 
</hibernate-mapping> 

Post類

public class Post : Entity 
{ 
    public virtual string Title { get; set; } 
    public virtual string Body { get; set; } 
    public virtual Post Parent { get; set; } 
    public virtual ICollection<Post> Children { get; set; } 
} 

User類

public class User : Entity 
{ 
    public virtual string Name { get { return this.Username; } } 
    public virtual string Username { get; set; } 
    public virtual string PasswordHash { get; set; } 
    public virtual string PasswordSalt { get; set; } 
    public virtual string Email { get; set; } 

    public virtual Profile Profile { get; set; } 
    public virtual ICollection<ObjectRole> Roles { get; set; } 
} 

編輯錯誤點的完整輸出加上前面的NHibernate日誌顯示正在構建的實體。

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 
+0

你能縮小範圍,使這個問題有點短?另外,請發佈異常堆棧跟蹤。 – 2010-12-18 20:45:58

+0

我正努力縮小範圍,尋找真正開始的指針。已附加完整的輸出。對於我來說,當查詢沒有返回結果時,我在應用程序的另一部分出現此錯誤似乎很奇怪。如果沒有實例,爲什麼要嘗試一個任務? – adambird 2010-12-18 22:11:57

回答

1

感謝Mauricio指點我回到堆棧跟蹤。這似乎是GetLimitString()的MySQL5Dialect實現的一個問題。將方言更改爲MySQLDialect從MySQL5Dialect似乎可以解決問題。

雖然,也許我很累,但是當我查看代碼時,MySQL版本似乎包含此異常的風險,而不是MySQL5版本。

MySQLDialect

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(); 
     } 

MySQL5Dialect

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(); 
     } 
相關問題