I am having trouble mapping our byte[] field. I've been looking for several solutions but none work so far. All I get is this exception:
The length of the byte[] value exceeds the length configured in the mapping/parameter.
Below is what I've got so far in the hbm.xml
<property name="Data" type="BinaryBlob">
<column name="attachmentData" sql-type="varbinary(max)"/>
</property>
Am I doing something not right here?
Update - Solution:
It turned out that I have done it incorrectly. We are inserting the byte[] via stored procedure so the property mapping has nothing to do with it. Instead, we need to tell NHibernate the type of the sprocs parameter like so:
query.SetParameter(param.Key, param.Value, NHibernateUtil.BinaryBlob);
NHibernate doesn't understand varbinary(max) and will use the default of 8000 bytes.
Therefore you will need to supply the number. I.e.
varbinary(2147483647)
I think used to work but is a regression bug.
Related
I'm trying to map an entity property in such way that it writes its value to a database column but retrieves its value using a formula.
To focus on the actual issue, I have simplified the example. In reality the formula is a bit more complex and is using an NHibernate filter.
<many-to-one cascade="all" class="Thing" lazy="false" name="MyThing"
formula="(SELECT Things.Value FROM Things WHERE Things.Id = MyThingId)">
<column name="MyThingId" />
</many-to-one>
The formula is ignored however, unless I remove the <column name="MyThingId" /> line.
How would I fix this mapping in order to have NHibernate use the formula?
I don't think it's possible to do exactly what you are trying.
Why not split the property in two? One readonly for the formula and the other read/write with a direct column mapping...
If you still want a single access point, you can map a third ignored propery that implements it's get and set accessors with the two first properties.
I have a little doubt for mapping of property in hbm file.
Sometimes I've mapped the string field of my db in this way:
<property name="MyPropName" column="MyColumnName" length="20" />
but the same mapping can be wrote in this way:
<property name="MyPropName" column="MyColumnName" type="String(20)" />
my question is...what's the better way?
If I omit "type" attributes for property tags it works, but I don't know if there are some contraindications. Can you tell me?
And last thing...are right this associations?
db varchar fields -> type "AnsiString"
db nvarchar fields -> type "String"
The "best practice" is to only override the defaults. So, for your example, the first form would be the best.
As for the second question: yes, they are correct.
You can find all the value types and default mappings here: 5.2.2. Basic value types
hello i got an application that uses nhibernate as orm, i need to store data that represents time,
whats the best way to do it?
nhibenate dont know to convert time field from db to a timespan, only string.
NHibernate supports DateTime, Ticks, TimeSpan and Timestamp. Make sure you are specifying the type explicitly on your mapping element as the different time types have different semantics so what NHibernate is guessing may not be correct.
If you are and are still having problems, modify your post to include the relevant portions of your entity, mapping file, and the actual problem you are encountering.
Edit:
For example, with the following class for a TimeSpan:
public class MyClass
{
// Other properties
// ...
// ...
public virtual TimeSpan MyTimeProperty { get; set; }
}
And the mapping file:
<!-- other properties -->
<property name="MyTimeProperty" type="TimeSpan" /> <!-- Note: NH expects the DB type to be DbType.Int64 -->
You indicate that you're trying to map a TimeSpan ("nhibenate dont know to convert time field from db to a timespan, only string"). If this is the correct type matching between .NET (typeof TimeSpan) and the database (DbType.Int64), NH should do this automatically (i.e. you shouldn't need to specify type="TimeSpan"). So if it's not working, I suspect there is a problem with the way you have things setup. It may be helpful if you post the property/field declaration with full signature, the <property> line for this property from your mapping file, and the column definition from the database.
Also, make sure you use nullables for your DateTimes that can be null in database.
DateTime? instead of just DateTime.
If not, NHibernate will attempt to initialize your date to a default value which probably isn't what you want.
typically definition of property/column looks like this:
<property name="DocumentSummary" column="DocumentSummary" length="100" type="String">
<column name="DocumentSummary" />
</property>
I was assuming that NHibernate will validate data using length attribute before inserting/updating a row. Unfortunately it seems to be invalid assumption. So question is if NHibernate is using length attribute for anything? Does it make sense to set it for each property?
It using it to create database definition sql. Look at SchemaExport class.
Also you might be able to programmically pull the lengths from the mappings, see this question. Note that that is for Java Hibernate, but I believe you might be able to translate that to NHibernate.
Yes, setting the Length property makes a different where you have string columns with a length that exceeds the default maximum length.
We have a column of type NVARCHAR(MAX). If we didn't set the length property, NHibernate would fail to set the string value if the value had a length greater than 4096 characters.
(This example uses Mapping-By-Code, because we're in 2017 :-)
classMapper.Property(
tickerFeed => tickerFeed.StaticTickerText,
propertyMapper =>
{
propertyMapper.Column("StaticTickerText");
propertyMapper.Length(int.MaxValue);
}
);
However, we found we could achieve the same result using IPropertyMapper.Type to stipulate that it was a large string.
classMapper.Property(
tickerFeed => tickerFeed.StaticTickerText,
propertyMapper =>
{
propertyMapper.Column("StaticTickerText");
propertyMapper.Type(NHibernateUtil.StringClob);
}
);
We ended up going with the propertyMapper.Type option, as it is more explicit.
Edit: Ryan raised a good point. I specifically want to be able to map to and from while still storing human-readable values in the database. That is, I don't want a bunch of enumeration integers in my database.
According to the documentation you can either leave the type attribute of the property in your mapping file blank or you define it and specify the class name of the enumeration.
Another way would be to convert the enumeration to an int and use the int as the mapped type.
You have to implement a custom IUserType. See this post.
I've never used NHibernate, but can't you just set the SQL datatype to int?
I think you can just set the type to string:
<property name="EnumProperty" Type="string" Length="50" NotNull="true" />