Mapping a long text string in Oracle and NHibernate - oracle

Using NHibernate 3.1 with both SQL Server and Oracle DBs, we need to store a text string that is longer than 4000 characters. The text is actually XML, but that is not important - we just want to treat it as raw text. With SQL Server, this is easy. We declare the column as NVARCHAR(MAX) and map it thusly:
<property name="MyLongTextValue" length="100000"/>
The use of the length property tells NHibernate to expect a string that may be longer than 4000 characters.
For the life of me, I cannot figure out how to make this work on Oracle 11g. I've tried declaring the column as both XMLTYPE and LONG with no success. In the first case, we end up with ORA-01461: can bind a LONG value only for insert into a LONG column when trying to insert a row. In the second case, the data is inserted correctly but comes back as an empty string when querying.
Does anyone know how to make this work? The answer has to be compatible with both SQL Server and Oracle. I'd rather not have to write custom extensions such as user types and driver subclasses. Thanks.

You should use something like this
<property name="MyLongTextValue" length="100000" type="StringClob"
not-null="false"/>
This should work with Oracle CLOB type and SqlServer NTEXT type.
Make sure the property on your model is nullable
public virtual string MyLongTextValue {get;set;}
You should always use the Oracle.DataAccess when dealing with CLOBs

For whom this may interest, I solved my problem following the step 3 of this article:
3. Using correct Mapping attributes: type="AnsiString"
Normally we can use type="String" default for CLOB/NCLOB. Try to use > type="AnsiString" if two steps above not work.
<property name="SoNhaDuongPho" column="SO_NHA_DUONG_PHO" type="AnsiString"/>
In my case I set it with FluentNHibernate:
.CustomType("AnsiString")

You might be interested in this article.
<property column="`LARGE_STRING`" name="LargeString" type="StringClob" sql-type="NCLOB" />

Related

How to use Dapper LINQ with TableDirect (without embedded SQL) with ORACLE?

I tried DapperExtensions, Dapper.Extensions.Linq and linq2dapper to no avail. I will try Dapper.SimpleCRUD-with-Oracle. I will probably settle with a Stored Procedure instead. I want to use TableDirect with no embedded SQL statement. How can I use Dapper and Linq with a TableDirect? Or, how can I use TableDirect without embedded SQL, and filter a table?
Following are my problems:
I could not create Predicate without run time error.
I need missing configuration
I got ORA error about table saying "column not correct, runtime error".
How to use Dapper LINQ with TableDirect (without embedded SQL) with ORACLE?
You can achieve this with simple Dapper. For example, look at the following code from Dapper:
public static IEnumerable<T> Query<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?));
Look at the last commandType parameter. It supports the TableDirect value that you are looking for.
As far as other extensions of Dapper you mentioned in question, I do not think they will support it. I know for sure Dapper Extensions do not support it; not sure about others.
This is because, those extensions are basic query generators written over Dapper. So, you are using them for generating the query and in that case, that parameter value will/should be Text. If you want to use other values, bypass the extension and use simple Dapper.
If you want to simply provide a table name or stored procedure name, why use query generator? Just use Dapper.
I used //https://github.com/jmo21/Dapper.SimpleCRUD-with-Oracle-/blob/master/Dapper.SimpleCRUD/SimpleCRUD.cs . No nuget package for this ORACLE dialect. It just obfuscates the WHERE clause, and it is an answer, when I the organization probably will not like SELECT.. FROM ... WHERE...
We don't have SQL injection possible in any case.

Entity Framework is padding out my text fields although they are not Fixed Length

I am building an MVC3 site using Entity Framework 4 and I'm having a problem with fixed length fields.
When I look at my code during debug it shows that MyEntity.Title="Hello name " with the title padded out to the maximum length of the field.
This is usually a question of having fixed field length in the EDMX file or using a char data type on the underlying database rather than a varchar. In this case neither of those is correct, however it is possible that the problem fields were of fixed length originally. I have manually changed each field in the EDMX ( and the model has been regenerated ) and the fields were never fixed length in the database ( which was the starting point for the application ) so I guess that the need to pad out the fields is being stored somewhere in the Entity Framework configuration and hasn't been updated.
The problem occurs in new records when they are added to the database- when the object is created the Title will be correct, when it is instanciated from the database it is padded.
What do I need to do in order to get rid of the padding, which is really screwing up my string comparisons unless I trim everything?
It turns out that in the .EDMX file the padded files were still listed as nchar. This wasn't visible through the Model Editor, the only way to change it was to right-click on the model in Visual Studio and select "open with..." then use an XML editor. The offending fields looked like this:
<Property Name="MyProperty" Type="nchar" Nullable="false" MaxLength="50" />
Changing the Type to nvarchar and running the template again seemed to clear the problem up.
Existing fields do not get updated in the model when you update it from the database. You either have to delete the entities from the model, or manually change those fields to the new values.
Check the property types in the Model Browser and make sure they are correct.
Change your Title field to have the Fixed Length property set equal to true. It's probably defaulting to none :)
Make sure you make the change in the dbase first and then update your edmx.

Enterprise Architect Oracle long field column properties

I have a little problem with Enterprise Architect by Sparx System.
Im trying to model database schema for Oracle. I created table with primary key with data type long. But when im trying to modify column properties (set AutoNum = true) I see empty properties. I read documentation of EA and saw that I need to setup this property to generate sequence syntax.
When I change data type to number, or switch database to mysql (for example) everything is alright, there are properties so Im able to modify AutoNum value.
Did you had similar problem and found solution ? or maybe im doing something wrong.
regards
It's becouse Oracle use sequence instead of autoincrement option. I've checked it and I think you have to use NUMBER column type and then set AutoNum property (you have to select Generate Sequences in options to get proper DDL code too). Instead of LONG data type you can set PRECISION and SCALE options on NUMBER type ie NUMBER(8) mean you can have 8 digits number and it can be set up to 38, so if you don't want to store info about every star in the universe will be enought for your scenario :)

How should I use UUID with JavaDB/Derby and JDBC?

I currently use INT as type for primary key in JavaDB (Apache Derby), but since I'm implementing an distributed system I would like to change the type to java.util.UUID. A few questions about this:
What datatype in JavaDB/Derby should I use for UUID? I have seen CHAR(16) FOR BIT DATA been mentioned but I don't know much about it. Is VARCHAR(16) an alternative?
How should I use it with JDBC? E.g. in an PreparedStatement, how should I set and get an UUID?
If I later would likte to change database to SQL Server, is there a compatible datatype to java.util.UUID?
Simply, How should I use UUID with JavaDB/Derby and JDBC?
UUID is a 128 bit value. The CHAR(16) FOR BIT DATA type reflects that it is bit data stored in character form for conciseness. I don't think VARCHAR(16) would work because it doesn't have the bit flag. The database would have to be able to convert the binary data to character data which deals with encoding and is risky. More importantly, it wouldn't buy you anything. Since a UUID is always 128 bits, you don't get the space savings from using VARCHAR over CHAR. So you might as well use the intended CHAR(16) FOR BIT DATA.
With JDBC, I think you use the get/setBytes() method since it is dealing with small amounts of binary data. (Not positive, would have to try this)
And no idea about the SQL Server part.
If you still want to use the UUID object in your code you can use fromString to create UUID objects from the DB and toString to store them in the DB.
You could convert the UUID to a string and store it as VARCHAR. Most UUID string formats are similar to this one: 32 digits separated by hyphens: 00000000-0000-0000-0000-000000000000, so then you'd want a VARCHAR(36), or make it something like VARCHAR(64) if you please, since it doesn't hurt to have extra 'space' available in your VARCHAR -- only the actual digits are stored.
Once you've converted it to a string, just call Statement.SetString to include it in your INSERT statement.

LINQ FormatException

I currently have an existing database and I am using the LINQtoSQL generator tool to create the classes for me. The tool is working fine for this database and there are no errors with that tool.
When I run a LINQ to SQL query against the data, there is a row that has some invalid data somehow within the table and it is throwing a System.FormatException when it runs across this row. Does anyone know what that stems from? Does anyone know how I can narrow down the effecting column without adding them one by one to the select clause?
Do you have a varchar(1) that stores an empty string?
You need to change the type from char to string in the designer (or somehow prohibit empties). The .net char type cannot hold an empty string.

Resources