basquang™ on clouds

December 23, 2009

“ORA-01461: can bind a LONG value only for insert into a LONG column” error in NHibernate

Filed under: NHibernate — basquang @ 8:08 AM

“ORA-01461: can bind a LONG value only for insert into a LONG column” happen when try to insert large text (> 4000 Unicode characters) using NHibernate and Oracle.

Following are steps work around to fix the problem:

1. Using Clob or NClob data type

Normally we use VARCHAR2 or NVARCHAR2 for text. But the max length of these data type is 4000. So If we want to store large text which greater than 4000 characters, we must change the data type to CLOB or NCLOB (for Unicode)

2. Using correct connection.driver_class: NHibernate.Driver.OracleDataClientDriver

We were using the NHibernate.Driver.OracleClientDriver which default to Microsoft’s Oracle provider (System.Data.OracleClient). We must change the driver_class property to NHibernate.Driver.OracleDataClientDriver

//c.SetProperty(NHibernate.Cfg.Environment.ConnectionDriver, "NHibernate.Driver.OracleClientDriver");
c.SetProperty(NHibernate.Cfg.Environment.ConnectionDriver, "NHibernate.Driver.OracleDataClientDriver");             
 
Or in config file
<property name="connection.driver_class">
        NHibernate.Driver.OracleDataClientDriver
</property>
 
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"/>

With three steps above, I solved the problem. Hope this help!

Here are some helpful links

http://msarchitectureadventures.blogspot.com/2009/10/problem-inserting-large-characters.html

http://rextang.net/blogs/past/archive/2005/11/16/2905.aspx

http://nhjira.koah.net/browse/NH-465

March 20, 2009

NHibernate, LINQ and Oracle

Filed under: NHibernate — basquang @ 9:43 AM
Ngày nay, các lập trình viên đứng trong hoàn cảnh vừa khó lại vừa dễ để tiếp cận lập trình. Nếu như trước đây, khi chúng ta viết một chương trình dù là rất nhỏ thì số dòng code mà bạn phải viêt lên đến hàng nghìn, thậm chí hàng chục, hàng trăm nghìn. Hơn nữa, chúng ta phải phân tích thiết kế, từ database sử dụng ER diagram, rồi thiết kế các objects sử dụng UML, rồi lại chuyện deployment cũng gặp khá nhiều khó khăn. Tuy nhiên, mặc dù số lượng công việc để hoàn thiện ra một chương trình rất là nhiều, xong việc lựa chọn phương án giải quyết cũng như khả năng kiểm soát dự án  là được đảm bảo, bởi vì hầu hết chúng ta làm bằng tay. Ngày nay, với sự phát triển nhanh chóng của công nghệ, từ Java đến .Net, từ EJB, J2EE, Swing, Hibernate trong Java hay WebService, WCF, WWF, WPF, Silverlight, LINQ, LamdaExpression, ADO.Net Data Service…trong .Net, các công việc phát triển phần mềm được tự động hóa khá là nhiều, do đó các lập trình viên nhàn hạ hơn, các dòng code cũng ít hơn, để thời gian trú trọng tới business của bài toán. Tuy nhiên, khi một dự án được phát sinh, thì quản trị dự án sẽ gặp khá nhiều khó khăn trong việc lựa chọn giải pháp cũng như là công nghệ. Họ không biết chọn Oracle hay SQL Server, chọn Java hay .Net, chọn LINQ to SQL hay Entity Framework…Hơn nữa, giải pháp mà họ lựa chọn phải đáp ứng được đặc thù yêu cầu của dự án. Ngoài ra họ phải giải quyết một vấn đề thường gặp với hầu hết các dự án là việc thao tác với CSDL. Đó là các thao tác CRUD (create, Read, Update, Delete). Và cũng đã có rất nhiều các framework hỗ trợ cho việc quản lý các thao tác này, mà lập trình viên không cần phải quan tâm đến việc thực thi nó như thế nào nữa. Ví dụ, bạn có thể dùng LINQ to SQL, Entity Framework, ADO.Net Data Service, Hibernate, hay NHibernate….Ngoài ra sự hỗ trợ của các Third-Party các Open OpenSource về code generation…càng làm cho công việc của các lập trình viên trở nên nhàn hạ hơn rất nhiều. Xong như đã nói ở trên, các lập trình viên phải đứng trước sự lựa chọn DÙNG CÁI NÀO? Với tôi, là một lập trình viên .Net, cũng không tránh khỏi sự lựa chọn đó.
Dự án của tôi sử dụng CSDL là Oracle và viết trên .Net 3.5. Tôi phải lựa chọn dùng công cụ cũng như Framework nào để giải quyết vấn đề thao tác cơ sở dữ liệu một cách an toàn nhất mà lại mang lại hiệu quả nhất. Nếu dùng SQL Server thì mọi thứ thật dễ dàng bởi tôi có thể dùng LINQ to SQL, Entity Framework hoặc ADO.Net Data Service. Tuy nhiên, thật khó khăn cho tôi khi mà các công nghệ đó không hộ trợ với CSDL Oracle từ phía Microsoft. Tôi đã thử tìm kiếm một số các Third-Party Provider hỗ trợ các công nghệ trên, xong cho tới thời điểm hiện tại thì chưa có cái nào thực sự làm tôi hài lòng. Tôi tin tưởng một ngày nào đó các công nghệ vừa kể trên được sự hỗ trợ trực tiếp từ phía các lập trình viên của Microsoft đối với CSDL là Oracle. Vậy tôi phải giải quyết dự án của tôi như thế nào?
Do có kinh nghiệm làm việc với .Net đặc biệt có chút hiểu biết về ORM (Object Relation Mapping) nên tôi cố gắng tìm kiếm một Open Source hỗ trợ ORM và .Net này. Đặc biệt có hỗ trợ Code Generation thì càng tốt. Có thể nói ORM là một phát kiến khá hay, tôi khá tâm đắc với phát kiến này. Điều đó giúp cho việc thiết kế chương trình trở nên đơn giản và ngắn gọn hơn rất nhiều. Nếu trước đây, tôi phải thiết kế database, sau đó tôi lại phải vận dụng kiến thứ UML thật là nhuần nhuyễn để thiết kế các class, thì ngày nay, tôi chỉ việc phân tích business của bài toàn thật tốt, sử dụng ORM tôi sẽ có một bản design class thật hòan hảo. Điều đó tôi thực sự thấy rất hay ở LINQ to SQL, ở Entity Framework, ở ADO.Net data service. Sau một hồi tìm kiếm online, tôi đã thử tiếp cận với NHibernate. Thật là thú vị, NHibernate đã để lại cho tôi ấn tượng tốt. Hỗ trợ Oracle, ORM mô hình, tool gen code support, đặc biệt cộng đồng hỗ trợ khá nhiều, không giống như các opensource khác, bạn có thể tìm thấy hầu như mọi thứ giải pháp hỗ trợ, nếu như bạn gặp phải vấn đề. Và tôi đã mạnh dạn áp dụng nó vào trong dự án của mình. Kết quả đem lại thật sự bất ngờ. Cấu trúc chương trình thật trong sáng, số dòng code mà các lập trình viên phải code cũng giảm đi rất nhiều
Sau đây là một số ví dụ:
 
Đây là domain model của bài toán
Domain này được tự động sinh ra từ MyGeneration với Template cho NHibernate
 
Đây là Mapping file
<class name="HardCopyConversion.DoanhNghiep,HardCopyConversion" table="DoanhNghiep" lazy="true">
    <id name="DoanhNghiepId" column="doanh_nghiep_id" type="long">
      <generator class="native" />
    </id>
    <many-to-one name="DaiDienTheoPhapLuat" column="dai_dien_theo_pl_id" cascade="save-update" not-null="true" />
    <property name="TenTv" column="ten_tv" type="string" />
    <property name="TenTa" column="ten_ta" type="string" />
……………….
<bag name="VanPhongDaiDien" inverse="true" lazy="true" cascade="delete">
      <key column="doanh_nghiep_id" />
      <one-to-many class="HardCopyConversion.VanPhongDaiDien,HardCopyConversion" />
    </bag>
  </class>
</hibernate-mapping>
 
Save Object to Database
 
 static void CreateDoanhNghiepAndSaveToDatabase()
        {           
            var doanhNghiep = new DoanhNghiep
            {
                DaiDienTheoPhapLuat = new ThongTinCaNhan {
                    HoTen = "Nguyen Ba Quang",
                    SoGiayChungThuc = "111811729"
                },
                Phongdkkd = new Phongdkkd
                {
                    DiaChi = new DiaChi {
                        TinhTp = "Ha Noi",
                        QuanHuyen = "Cau Giay",
                        PhuongXa = "Dich Vong Hau",
                        SoNhaDuongPho = "Nguyen Phong Sac"
                    },
                },
                DiaChi = new DiaChi {
                    TinhTp = "Ha Noi",
                    QuanHuyen = "Hai Ba Trung",
                    PhuongXa = "Nga Tu Vong",
                    SoNhaDuongPho = "352 Giai Phong"
                },
                TenTv = "Toan Cau",               
            };           
            using (ISession session = OpenSession())
            {
                using (ITransaction transaction = session.BeginTransaction())
                {                 
                    session.Save(doanhNghiep);                   
                    transaction.Commit();
                }
                Console.WriteLine("Saved  to the database");
            }
            SaveChiNhanh(doanhNghiep);
        }
 
Sử dụng LINQ để truy xuất data
 
 var query = from tinhTPLinq in session.Linq<DiaChi>()
                                 where tinhTPLinq.TinhTp == "Hà Nội"
                                 select tinhTPLinq;
                     foreach (var ttp in query)
                     {
                         Console.WriteLine("TP:" + ttp.TinhTp);
                     }

Create a free website or blog at WordPress.com.