I have a nvarchar(2000) column in a SQL Server 2005 database, and have mapped this into NHibernate as:
<property name="Query" column="`Query`" type="String" length="2000" not-null="false"/>
The DTO class just presents a string property:
public virtual string Query { get; set; }
If I set the query to a string of > 2000 characters I get an exception from SQL server to the effect of:
"String or binary data would be
truncated. The statement has been
terminated."
What I want is for this truncation to just happen automatically and silently. I could override the virtual property and force the truncation on the property set, but feel there should be a way to get this behaviour by default, either via the NHibernate mapping or even as a SQL server setting.
Am I missing anything ... I don't want to change the db schema to allow longer strings.
Create a custom User Type and which truncates the string if it's longer than 2000 chars. Here is sample of creating User Type
<property name="Query" type="Common.Nhibernate.Types.StringTruncType, Common" column="`Query`" type="String" length="2000" not-null="false"/>
Related
I'm using nHibernate 4.1.4 MappingByCode. My Dialect is
public class Dialect : NHibernate.Dialect.MsSql2012Dialect
{
protected override void RegisterKeywords()
{
base.RegisterKeywords();
RegisterKeyword("user");
}
}
My config is setting
config.SetProperty(Environment.Hbm2ddlKeyWords, "keywords");
I have a table named User.
SQL error is thrown that invalid table name User is invalid. nHibernate fails to wrap it in brackets.
Any ideas?
Keywords are used for different purpose...
what we need is ad hoc table name escaping
5.3. SQL quoted identifiers
You may force NHibernate to quote an identifier in the generated SQL
by enclosing the table or column name in back-ticks in the mapping
document. NHibernate will use the correct quotation style for the SQL
Dialect (usually double quotes, but brackets for SQL Server and
back-ticks for MySQL).
<class name="LineItem" table="`Line Item`">
<id name="Id" column="`Item Id`"/><generator class="assigned"/></id>
<property name="ItemNumber" column="`Item #`"/>
...
</class>
I.e. in mapping, we need to escape table name:
"`user`"
Keywords, defined in configuration of the dialect, would help NH parser when working with custom sql statements. E.g. in formulas, subselects.
I have a class with a field:
protected DateTime insertDate;
This is mapping for this fiels:
<property name="InsertDate" access="field.camelcase" update="false" />
This field is set when with ctor
public DocuBase(DateTime insertDate)
and is persisted only when row is added to the database. I don't need property for it at all, no setter & no getter. I worked in NHibernate 3.
And now, I've moved from NHiberbate 3 to NHibernate 3.3.1, and I get this exception when session factory is created:
Could not find the property 'InsertDate', associated to the field
'insertDate', in class 'XXXX'
Why is is happening & how can I change mapping in order to get rid of the exception?
EDIT: Below answer is completly correct. But for those of you that don't need/don't want to have a property, and only field, there's another solution:
set name attribute to field name (in my case it is insertDate) and remember to have correct column name
<property name="insertDate" column="InsertDate" access="field.camelcase" update="false" />
It is case sensitivity, this will work.
<property name="insertDate" column="InsertDate" update="false" />
Looks like in release 3.1.0, there was a breaking change
NH today accepts code below. It would be better if this would throw - it causes problem when configurate NH (or 3rd party tools) other ways than by hbm, using the property name (or memberinfo) of the public interface.
[hbm]
<property name="Name" access="field.camelcase" />
[code]
string name;
public virtual string SomeThingCompletelyDifferent{
get {return name;}
set{name=value;}
}
Note: This will be a breaking change.
ps - updated answer to remove reference to use Property with private set as this was not what was being looked for and above breaking change is more relevant.
All of my datamodels have field DateAdded. When the user (through MVC Web API) sends a request to save a model, the serverside populates this field with a DateTime object, and then proceeds to save the object via hibernate.
Now consider the case of updating. Even if the user modifies the DateAdded field manually, it should not change the value in the database. Is there a way that I can specify for this field to NOT be updated, regardless of what the user provides? If the field is not populated by the user, the datetime field becomes null, which is also no good.
Turns out there's a property for this you can set in the hbm file!
Simply set update="false" on all properties that you don't want to be updateable. Sorry for not doing more research before wasting precious SO resources.
Change all your mappings to:
<property name="DateAdded" update="false">
<column name="DateAdded" sql-type="smalldatetime" not-null="true" />
</property>
I got this example from the adobe coldfusion documentation, some of the names are changed but everything else is the same, unless I am just so frustrated that I have missed a letter.
user.cfc:
/**
*#persistent
*/
component
{
property name="id" fieldtype="id" generator="native";
property name="userName" type="string" length="100";
property name="Credential" fieldtype="one-to-one" cfc="model.user.credentials";
}
credentials.cfc:
/**
*#persistent
*/
component
{
property name="id" fieldtype="id" generator="foreign" params="{property='userinfo'}";
property name="userinfo" fieldtype="one-to-one" cfc="model.user.user" constrained="true";
property name="passwordHash" type="string";
}
no matter how I word it, after searching many sites, I still get a error of:
Error while resolving the relationship Credential in cfc user. Check the column mapping for this property.
I have checked that both cfcs are accessible by coldfusion by removing the one-to-one properties and the tables have been created successfully.
I am using SQL Server 2008 with Coldfusion 9.0.1 under Apache 2.2 web server.
I am new to ORM and Hibernate but have successfully created different types of relationships and will confess to a less then expert level of coldfusion.
Thanks, this is really bothering me as this came directly from the coldfusion documentation.
Do you have a mapping for model?
If not, add one, or you could try:
property name="Credential" fieldtype="one-to-one" cfc="credentials";
Consider the following simple C# class:
public class Entity
{
public Entity() { }
public virtual int Id { get; private set; }
public virtual DateTime DateCreated { get; private set; }
}
Mapped with the following simple NHibernate mapping:
<class name="Entity" mutable="false">
<id name="Id">
<generator class="native">
</id>
<property name="DateCreated"/>
</class>
To the following simple database schema:
CREATE TABLE Entity (
Id int IDENTITY(1,1) PRIMARY KEY,
DateCreated datetime NOT NULL DEFAULT getUtcDate()
)
When creating a new instance of the Entity and saving to the database, how do you instruct NHibernate to use the database's default value for the DateCreated column if its value is null? Alternatively, how can I specify that NHibernate should use the result of the getUtcDate() function as the value for the DateCreated field upon insertion?
While I could easily add
DateCreated = DateTime.Now;
into the Entity constructor, this is using the application server's local clock, and I need to use the database's local clock to ensure consistency when there are multiple application servers each with their potentially non-synchronized local clocks.
You can specify that the property is generated by the database:
NHibernate Mapping - property
So for your case you would want to specify:
generated="insert"
This way NHibernate knows after an INSERT it will have to refresh the entity, but after updates DateCreated will not be changed.
You might also have to specify:
update="false" insert="false"
I've never used generated, and I'm not sure if NHibernate infers to set those or you have to do it explicitly.
I had a similar issue. I had to add the attribute dynamic-insert="true" to my class mapping.
From the documentation:
dynamic-insert (optional - defaults to false): specifies that INSERT SQL should be generated at runtime and contain only the columns whose values are not null.