NHibernate 2.1.2 throwing DateTime null overflow exception - nhibernate

I'm having a similar problem to these questions:
NHibernate 2.* mapping files: how to define nullable DateTime type (DateTime?)?
NHibernate won't persist DateTime SqlDateTime overflow
I'm using NHibernate 2.1.2 and FluentNhibernate 1.0.0.636. With NHibernate 2.x the nullable DateTime? issue should be fixed and I shouldn't have to do anything special with my mapping. Accordingly, all my DateTime properties are simply set like so:
public virtual DateTime? CreatedOn { get; set; }
In my database (SQL2008), all DateTime properties are set to allow null. I have my NHibernate config file setup to use the SQL2008 dialect:
<property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>
NHibernate works fine for anything that does not include a DateTime. For reference, here's the exact error I'm receiving:
> at
> NHibernate.AdoNet.SqlClientSqlCommandSet.ExecuteNonQuery()</StackTrace><ExceptionString>System.Data.SqlTypes.SqlTypeException:
> SqlDateTime overflow. Must be between
> 1/1/1753 12:00:00 AM and 12/31/9999
> 11:59:59 PM.
If I run SQL Profiler, I can see the last command that NHibernate attempts to execute (this was a very long statement, so I've truncated it):
exec sp_executesql N'UPDATE Projects SET Job = #p0, CreatedOn = #p1, .. WHERE (Where Clause), #p0=219221, #p1=NULL
If I execute this statement as a query, SQL persists it fine, doesn't complain at all!
What's going on?

Your DateTime properties are probably set to DateTime.MinValue (1/1/0001) instead of null or a value in the valid range for a DateTime column.

I don't know why, but this works here. Unlike the example in the link, mine are DateTime? so .... I do not know why it works, but it does.

I had this same issue. At first I thought I fixed it by switching my sql type from a nullable date to a nullable datetime. However, that was a mirage. The root cause was a cascading update on another newly added table.
This would have been quickly resolved if everyone (but especially MS) threw more descriptive errors. Cest la vie.

Related

NHibernate paging for SQL Server 2012

According to this issue:
https://nhibernate.jira.com/browse/NH-3038
NHibernate should create efficient paging queries for SQL Server 2012.
I have NHibernate 3.3.3GA. I set the dialect in the config file:
<property name="dialect">NHibernate.Dialect.MsSql2012Dialect</property>
and while debugging I see that indeed the session factory has MsSql2012Dialect.
But still the following code:
session.Query<TestEntity>().Skip(1).Take(1).ToList()
generates the same T-SQL as the old SQL Server 2008 dialect does:
exec sp_executesql N'
SELECT TOP (#p0) EntityId1_, Version1_, Name1_, Something1_
FROM (select testentity0_.EntityId as EntityId1_, testentity0_.Version as Version1_, testentity0_.Name as Name1_, testentity0_.Something as Something1_, ROW_NUMBER()
OVER(ORDER BY CURRENT_TIMESTAMP)
as __hibernate_sort_row from tTestEntity testentity0_) as query
WHERE query.__hibernate_sort_row > #p1
ORDER BY query.__hibernate_sort_row',N'#p0 int,#p1 int',#p0=1,#p1=1
How do I make NHibernate Linq provider to use the paging features of MsSql2012Dialect and generate a query with OFFSET and FETCH?
Solution:
Thanks to Diego Mijelshon who led me to the right source code, I managed to implement a quick fix which seems to work fine. We are using it for some months already, no problems yet.
Here is what I did:
I imported the following classes from the NHibernate source into my own library:
https://github.com/nhibernate/nhibernate-core/blob/967091f5c22a16a576f46144055f78c0f373ffcd/src/NHibernate/SqlCommand/Parser/SqlTokenizerExtensions.cs
https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Dialect/MsSql2012Dialect.cs
https://github.com/nhibernate/nhibernate-core/blob/967091f5c22a16a576f46144055f78c0f373ffcd/src/NHibernate/SqlCommand/Parser/SqlTokenizer.cs
https://github.com/nhibernate/nhibernate-core/blob/967091f5c22a16a576f46144055f78c0f373ffcd/src/NHibernate/SqlCommand/Parser/SqlParserUtils.cs
https://github.com/nhibernate/nhibernate-core/blob/967091f5c22a16a576f46144055f78c0f373ffcd/src/NHibernate/SqlCommand/Parser/SqlToken.cs
As far as I remember, I did some modifications to remove unnecessary bits of code.
In SqlTokenizerExtensions I left only these two extensions:
public static bool TryParseUntil(this IEnumerator<SqlToken> tokenEnum, string keyword)
public static bool TryParseUntilFirstMsSqlSelectColumn(this IEnumerator<SqlToken> tokenEnum)
SqlTokenizer, SqlToken, SqlParserUtils, MsSql2012Dialect - no changes.
Then I just set <property name="dialect"> to the new MsSql2012Dialect in my config file for NHibernate, and now my paging queries are clean and simple.
If you look at NH-3038, you'll see that it's fixed in master/vNext. That means NH4.
You can still get the updated dialect from https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Dialect/MsSql2012Dialect.cs, include it in your project and reference it (adding the correct assembly name).

Now() in ColdFusion (Railo) ORM entity property as a default?

A common design I use is to set a date column with the current date as the default. For SQL Server I use getDate() and for MySQL now() or current_timestamp.
Implementing a MySQL solution in ORM, seemed the way to do it would be:
property name="dtSaved" ormtype="date" dbdefault="now()";
However, this isn't working, but isn't throwing an error either. When I run ORMReload(), it seems to get stuck on this table, and none of the entities that come after (alphabetically) get created. (I'm using dbcreate="dropcreate")
Note that this is Railo 3.3.1, not Adobe ColdFusion 9.
You can set a dynamic default value in your constructor, so something like this:
component persistent="true" {
property name="measurementDate" ormtype="date";
function any init(){
if (IsNull(variables.measurementDate)){
variables.measurementDate = Now();
}
return this;
}
}
Comment by John Whish – November 22, 2010
from:
http://www.aliaspooryorik.com/blog/index.cfm/e/posts.details/post/coldfusion-9-orm-example-215

HsqlException: data exception

I am using hsqldb version 2.2.5 in my application sometimes I am getting
org.hsqldb.HsqlException: data exception: string data, right truncation.
So I want to know what are the possible reasons for that. I am not inserting any data like longvarchar in a varchar column.
http://sourceforge.net/tracker/index.php?func=detail&aid=2993445&group_id=23316&atid=378131
I searched above link but could not get proper feedback.
Given below the exception stack
This exception is not happening frequently.
So what could be the reason for that and how to set the data type length in script file to increase at run time ?
java.sql.SQLException: data exception: string data, right truncation
at org.hsqldb.jdbc.Util.sqlException(Util.java:255)
at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(JDBCPreparedStatement.java:4659)
at org.hsqldb.jdbc.JDBCPreparedStatement.executeUpdate(JDBCPreparedStatement.java:311)
at com.dikshatech.agent.db.NodesRuntimeTable.persistData(NodesRuntimeTable.java:151)
at com.dikshatech.agent.jobs.WorkFlowJob.execute(WorkFlowJob.java:108)
at org.quartz.core.JobRunShell.run(JobRunShell.java:216)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:549)
Caused by: org.hsqldb.HsqlException: data exception: string data, right truncation
at org.hsqldb.error.Error.error(Error.java:134)
at org.hsqldb.error.Error.error(Error.java:104)
at org.hsqldb.types.CharacterType.castOrConvertToType(CharacterType.java:523)
at org.hsqldb.types.CharacterType.convertToType(CharacterType.java:638)
at org.hsqldb.StatementDML.getInsertData(StatementDML.java:921)
at org.hsqldb.StatementInsert.getResult(StatementInsert.java:124)
at org.hsqldb.StatementDMQL.execute(StatementDMQL.java:190)
at org.hsqldb.Session.executeCompiledStatement(Session.java:1344)
at org.hsqldb.Session.execute(Session.java:997)
at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(JDBCPreparedStatement.java:4651)
The maximum size of a VARCHAR column is user-defined. If the inserted data is larger than this, an exception is thrown. The example below defines a table with a VARCHAR(100) column, which limits the size to 100 characters.
CREATE TABLE T (ID INT, DATA VARCHAR(100))
You can use a database manager and execute the SCRIPT command to see all your table definitions and their column size. Alternatively, SELECT * FROM INFORMATION_SCHEMA.COLUMNS shows the characteristics of each column.
You can use the ALTER TABLE table_name ALTER COLUMN col_name SET DATA TYPE to increase the size of an existing column.
For Hibernate/HSQLDB automatically generated schema via #Column annotation on #Entity field of type String you might need to provide length atrribute. Otherwise the length will default to 255 and long input will not fit:
#Lob
#Column(name="column_name", length = 1000)
private String description;
Your field length is not large enough. I used the LONGVARCHAR data type to fix this error.
CREATE TABLE "DEMO_TABLE" ("ID" NUMBER(19,0), "MESSAGE" LONGVARCHAR);
WARNING: Rant follows...
Yep, the error message java.sql.SQLException: data exception: string data, right truncation... makes total sense only after you know what's wrong. Occasionally I find a clear, well-written error message, meant to inform users. The time it takes to write one will be returned 100 fold (or more depending on usage), but usually to others. Hence, there is too little incentive for most to spend the time. It can however come back to benefit the product, as with the Spring Framework which has generally superior error messages.
I'm sure stackoverflow.com does not mind. Poor error messages likely drive people here every minute of every day!
I encountered this error while using Hibernate with HSQLDB. Instead of the usual String field, the offender was a serializable field.
Hibernate mapping file was
<hibernate-mapping package="in.fins.shared">
<class name="Data">
<id name="id" column="id">
<generator class="uuid" />
</id>
<property name="date" column="Date" />
<property name="facts" column = "facts" type="serializable" />
</class>
</hibernate-mapping>
For facts field, which is set to serializable, Hibernate creates a column of type VARBINARY with maximum length 255 in HSQLDB. As serialized object size was more than this size data exception: string data, right truncation was thrown by HSQLDB.
Changing the facts column to Blob with sql-type attribute resolves the problem.
<property name="facts" type="serializable">
<column name="facts" sql-type="blob" />
</property>
I actually faced the same problem, and got fixed relatively quickly.
In my case I've declared a DB table column column like this: description VARCHAR(50), but I was trying to insert a longer string/text in there, and that caused the exception.
Hope this will help you :)
I had the same problem as you describe while testing with HSQLDB.
I'm using hibernate as JPA implementation and this is my mapping class:
#Column (name = "file")
private byte[] file;
In production I'm using PostgreSQL and the problem don't shown up, but with HSQL I had to add the #Type annotation in my mapping to solve that error:
#Column (name = "file")
#Type(type = "org.hibernate.type.MaterializedBlobType")
private byte[] file;
There are many implementations of types. You can take a look at hibernate-core jar, inside the package org.hibernate.type and pick some that matches your mappings.
This error occurs in some scenario's but in the following scenario it is difficult
to retrieve the cause, assume following scenario:
Assume the following entity
#Entity
public class Car {
private String name;
#ManyToOne
#JoinColumn(name = "ownerId")
private Owner owner;
...
When the annotation '#ManyToOne' would be forgotten, but the annotation ' #JoinColumn(name = "ownerId")' would be present! This error would occur, which doesn't really indicate the real issue.

How does NHibernate Projections.Max work with an empty table?

I'm trying to get the maximum value of an integer field in a table. Specifically, I'm trying to automatically increment the "InvoiceNumber" field when adding a new invoice. I don't want this to be an autoincrement field in the database, however, since it's controlled by the user -- I'm just trying to take care of the default case. Right now, I'm using
session.CreateCriteria<Invoice>()
.SetProjection(Projections.Max("InvoiceNumber"))
.FutureValue<int>();
to get the biggest invoice number already in the database. This works great, except when there are no invoices already in the database. Then I get a System.ArgumentException: The value "" is not of type "System.Int32" and cannot be used in this generic collection. Changing to FutureValue<int?>() didn't solve the problem. Is there a way to tell NHibernate to map the empty string to null? Or is there a better way to accomplish my goal altogether?
The stack trace of the exception (at least the relevant part) is
NHibernate.HibernateException: Error executing multi criteria : [SELECT max(this_.[InvoiceNumber]) as y0_ FROM dbo.[tblInvoice] this_;
SELECT this_.ID as ID647_0_, this_.[NHVersion] as column2_647_0_, this_.[Description] as column3_647_0_, this_.[DiscountPercent] as column4_647_0_, this_.[DiscountDateDays] as column5_647_0_, this_.[PaymentDueDateDays] as column6_647_0_, this_.[Notes] as column7_647_0_, this_.[DiscountDateMonths] as column8_647_0_, this_.[PaymentDueDateMonths] as column9_647_0_, this_.[DiscountDatePeriod] as column10_647_0_, this_.[DiscountDateMonthlyDay] as column11_647_0_, this_.[DiscountDateMonthlyDayDay] as column12_647_0_, this_.[DiscountDateMonthlyDayMonth] as column13_647_0_, this_.[DiscountDateMonthlyThe] as column14_647_0_, this_.[DiscountDateMonthlyTheDOW] as column15_647_0_, this_.[DiscountDateMonthlyTheMonth] as column16_647_0_, this_.[DiscountDateMonthlyTheWeek] as column17_647_0_, this_.[PaymentDueDatePeriod] as column18_647_0_, this_.[PaymentDueDateMonthlyDay] as column19_647_0_, this_.[PaymentDueDateMonthlyDayDay] as column20_647_0_, this_.[PaymentDueDateMonthlyDayMonth] as column21_647_0_, this_.[PaymentDueDateMonthlyThe] as column22_647_0_, this_.[PaymentDueDateMonthlyTheDOW] as column23_647_0_, this_.[PaymentDueDateMonthlyTheMonth] as column24_647_0_, this_.[PaymentDueDateMonthlyTheWeek] as column25_647_0_ FROM dbo.[tblTermsCode] this_;
] ---> System.ArgumentException: The value "" is not of type "System.Int32" and cannot be used in this generic collection.
Parameter name: value
at System.ThrowHelper.ThrowWrongValueTypeArgumentException(Object value, Type targetType)
at System.Collections.Generic.List`1.VerifyValueType(Object value)
at System.Collections.Generic.List`1.System.Collections.IList.Add(Object item)
at NHibernate.Impl.MultiCriteriaImpl.GetResultsFromDatabase(IList results)
use....UniqueValue<int?>();
NH uses a non-generic IList in their MultiCriteria implementation. Which is used for FutureValue batching. see here for why List<int?> fails to add null through it's IList implementation. I'm surprised I've never run into this before. Avoid using nullable value types with Future or MultiCriteria.
With the QueryOver API:
Session.QueryOver<T>()
.Select(Projections.Max<Statistic>(s => s.PeriodStart))
.SingleOrDefault<object>();
if nothing is returned its null, otherwise cast the result as numeric

Error converting data type varchar to datetime when running raw SQL but not when called by LINQ to SQL

A client is getting an error when running my code. They sent me the SQL from profilder.
When I paste it into SQL Server Management Studio it fails with: Error converting data type varchar to datetime
However it doesn't fail when I run it on my local dev box or another clients production sever.
To test I created a simple app with a L2S datacontext containing one entity that looks something like:
public class UserAccount
{
public int Id { get; set; }
public string Username { get; set; }
public DateTime? LastActivity { get; set; }
}
Insert a record and then update it:
var account = db.UserAccounts.Single(a => a.Username == "Mojo");
account.LastActivity = DateTime.Now;
db.SubmitChanges();
The records gets updated in the database. But when I grab the T-SQL from Profiler:
exec sp_executesql N'UPDATE [UserAccount] SET [LastActivity] = #p2 WHERE ([Id] = #p0) AND ([Username] = #p1) AND ([LastActivity] IS NULL)',N'#p0 int,#p1 nvarchar(4),#p2 datetime',#p0=1,#p1=N'Mojo',#p2='2009-11-10 14:04:41.7470000'
and execute it in SQL Server Management Studio I get: Error converting data type varchar to datetime
What am I missing?
The problem is with the extra zeroes at the end of the date:
'2009-11-10 14:04:41.747' (works)
'2009-11-10 14:04:41.7470000' (error converting...)
The four extra zeroes are probably just visible in the Visual Studio debugger. LINQ does not sent them to SQL Server.
Are you using identical connections in Management Studio as in your test app? It sounds like this isn't the case the connections have different regional settings, causing the date to be parsed differently.
Different versions of SQL Server perhaps?
The extra zeros in the date would make it a datetime2 type which would be acceptable in 2008 but not 2005.
DATETIME should have only 3 digits after second, DATETIME2 has 7 digits after second. Seems that the string is formatted for DATETIME2.
I got this error once I was trying to Insert the date time as '1/1/0001 12:00:00 AM'
Perhaps it may help somebody: in my case, the problem was that copying the query from SQL Profiler split the lines at the bottom where the parameters are, including several varchar parameters which contained timestamps. I believe this would fail both datetime and datetime2.
So, I had something like:
#p250=4, #p251=2, #p252=2, #p253=N'2021-03-23
15:20:00.123'