亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Oracle中Clob類型處理解析

系統 1882 0
?
最近利用NHibernate映射類型為Clob字段在插入數據時發現當字符的字節數(一個半角字符一個字節,一個全角字符兩個字節)在2000-4000之間時報錯(ORA-01461:僅可以插入LONG列的LONG值賦值)。經過不斷查找資料和自己的試驗該問題終于得到解決,下邊我將自己的心得給大家做一個分享。

?

準備

系統環境 xp+.net2.0+oracle9i

?

表結構(由于是測試,表結構隨便建了一張) XX?

字段名

類型

ID

VARCHAR2(70)

TEST

CLOB

?

?

測試

?

方式 1 :直接將 CLOB 的值拼寫在 SQL 語句中。

代碼:

  1. string?id?=?Guid.NewGuid().ToString();
  2. OracleCommand?cmd?=?Conn.CreateCommand();
  3. cmd.CommandText?=?"insert?into?xx(id,test)?values('"?+?id?+?"','"?+?data?+?"')";//?data是一個變量,存儲你要插入的字符串
  4. cmd.ExecuteNonQuery();

情況分析 :

?? ? 當d ata 的長度大于 4000 時報錯 (ORA-01704: 文字字符串過長 ) ,小于或等于 4000 時正常插入。

原因分析:

? ? 之所以會出現長度大于 4000 時報錯,是因為 Oracle 中有 SQL 語句中兩個單引號之間的字符數不能大于 4000 的限制。'" + data + "' data在sql語句之間,當data的值大于4000個字節時就會報錯。

解決辦法:

?? 這種方式比較棘手,但有更好的方式,下邊會講到。

?

方式 2 :采用參數形式。

代碼:

  1. string?id?=?Guid.NewGuid().ToString();
  2. OracleCommand?cmd?=?Conn.CreateCommand();
  3. cmd.CommandText?=?"insert?into?xx(id,test)?values('"?+?id?+?"',:p1)";
  4. OracleParameter?p1?=?new?OracleParameter("p1",?OracleType.Clob);
  5. p1.Value?=?data;?//?data是一個變量,存儲你要插入的字符串
  6. cmd.Parameters.Add(p1);
  7. cmd.ExecuteNonQuery();

情況分析 :

??? 采用這種方式能夠正常插入。所以推薦用這種方式。

原因分析:

??無

解決辦法:

? ?

?

方式 3 :采用參數形式,但是參數類型寫為 OracleType. NVarChar

代碼:

  1. string?id?=?Guid.NewGuid().ToString();
  2. OracleCommand?cmd?=?Conn.CreateCommand();
  3. cmd.CommandText?=?"insert?into?xx(id,test)?values('"?+?id?+?"',:p1)";
  4. OracleParameter?p1?=?new?OracleParameter("p1",?OracleType.?NVarChar);
  5. p1.Value?=?data;?//?data是一個變量,存儲你要插入的字符串?
  6. cmd.Parameters.Add(p1);
  7. cmd.ExecuteNonQuery();

情況分析 :

??? 為什么要寫這種方式,因為這種方式和采用 NHibernate 的方式很相似,先看看在這種方式會產生什么情況。當 data 的字節數在 0-2000 之間時正常插入,大于 4000 時也正常插入,但在 2000-4000 時則失敗,報錯 (ORA-01461: 僅可以插入 LONG 列的 LONG 值賦值 )

原因分析:

?? 沒有采用對應的 Oracle 類型。

解決辦法:

? ? 采用OracleType.Clob

?

?

下邊采用NHibernate插入數據,NHibernate具體怎用不在本次討論范圍。

NHibernate采用的版本為1.2.1.4000。

下邊大至把簡要配置寫下。

?

App.config

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

? <configSections>

??? <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />

? </configSections>

? <nhibernate>

??? <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" />

??? <add key="hibernate.connection.driver_class" value="NHibernate.Driver.OracleClientDriver" />

??? <add key="hibernate.connection.isolation" value="ReadCommitted"/>

? ??<add key="hibernate.dialect" value="NHibernate.Dialect.Oracle9Dialect" />

??? <add key="hibernate.connection.connection_string"

???????? value="Data Source=Orcl_192.168.0.232;User ID =icqs_test;Password=icqs_test" />

??? <add key="show_sql" value="true" />

??? <add

?????????? key="hibernate.adonet.batch_size"

?????????? value="100"

?????? />

? </nhibernate>

</configuration>

?

xx.cs

  1. using ?System;
  2. using ?System.Collections.Generic;
  3. using ?System.Text;
  4. namespace ?Test.Enties
  5. {
  6. ????[Serializable]
  7. ????public?class?Xx
  8. ????{
  9. ????????public?Xx()
  10. ????????{
  11. ????????}
  12. ????????private?string?id;
  13. ????????public?virtual?string?Id
  14. ????????{
  15. ????????????get?{?return?id;?}
  16. ????????????set?{?id?=?value;?}
  17. ????????}
  18. ????????public?virtual?string?Test
  19. ????????{
  20. ????????????get?{?return?test;?}
  21. ????????????set?{?test?=?value;?}
  22. ????????}
  23. ????????private?string?test;
  24. ????}
  25. }

xx.hbm.xml

<?xml version="1.0" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Test.Enties" assembly="Test">

? <class name="Xx" table="xx" lazy="true">

?

??? <id name="Id" column="id" type="String">

????? <generator class="assigned"/>

??? </id>

??? <property column="test" type="StringClob" name="Test" length="2147483647" />

?

? </class>

</hibernate-mapping>

?

說明:

<add key="hibernate.connection.driver_class" value="NHibernate.Driver.OracleClientDriver" />這里的驅動用的NHibernate.Driver.OracleClientDriver,其實是對微軟的OracleClient的封裝啦,其實內部還是調用微軟的OracleClient的東東。引用System.Data.OracleClient.dll即可OracleClient。

?

做好上邊的配置后,便有了以下的方式

方式 4 :采用 NHibernate

代碼:

  1. string?id?=?Guid.NewGuid().ToString();
  2. Xx?xx?=?new?Xx();
  3. xx.Test?=?data;?//?data是一個變量,存儲你要插入的字符串
  4. xx.Id?=?id;
  5. ISession?session?=?SessionFactory.OpenSession();
  6. session.Save(xx);
  7. session.Flush();

情況分析 :

?? data 的字節數在 0-2000 之間時正常插入,大于 4000 時也正常插入,但在 2000-4000 時則失敗,報錯 (ORA-01461: 僅可以插入 LONG 列的 LONG 值賦值 ). 情況和方式 3 的情況一樣。

原因分析:

??? NHibernate在用OracleClient映射StringClob時,設置參數類型為OracleType.?NVarChar,導致插入有BUG。網上有人推測是OracleClient的BUG所致,理由是換用OracleDataAccess即可解決。

?

為什么說NHibernate將參數類型設置為OracleType.NVarChar呢?看下邊

?

?

  1. 找到NHibernate的源代碼,把它加入你的工程。記得不要移動NHibernate位置直接加入工程,直接在NHibernate的安裝目錄引用進來。

?

?

?

?? 2. 在Test解決方案中添加NHibernate的項目引用。

?

經過上邊兩個步驟我們就可以跟蹤調試NHibernate了

?

  1. 跟蹤代碼session.Save(xx);看看它究竟做了啥。

當我們跟進CommandSetBatchingBatcher時,可以得到以下信息(如圖中的調試信息)。CurrentBatch類型是OracleClientCommandSet,OracleClientCommandSet看源碼得知是對微軟的OracleCommandSet的封裝,因為這個類 internal sealed class ,所以我們的程序里是找不到這個類的,不過 NHibernate 通過反射使用了它的功能。OracleCommandSet 可能用作批處理的,就是一次處理多個SQL語句的,不是太了解,誰知道請指教。

?

?

CommandSetBatchingBatcher的源碼

  1. internal?class?OracleClientCommandSet?:?DbCommandSet<OracleConnection,?OracleCommand>
  2. ????{
  3. ????????private?static?System.Type?oracleCmdSetType;
  4. ????????static?OracleClientCommandSet()
  5. ????????{
  6. ????????????Assembly?sysDataOracleClient?=?Assembly.Load("System.Data.OracleClient,?Version=2.0.0.0,?Culture=neutral,?PublicKeyToken=b77a5c561934e089");
  7. ????????????oracleCmdSetType?=?sysDataOracleClient.GetType("System.Data.OracleClient.OracleCommandSet");
  8. ????????????Debug.Assert(oracleCmdSetType?!=?null,?"Could?not?find?OracleCommandSet!");
  9. ????????}
  10. ????????protected?override?object?CreateInternalCommandSet()
  11. ????????{
  12. ????????????return?Activator.CreateInstance(oracleCmdSetType,?true);
  13. ????????}
  14. }

跟蹤CurrentBatch可以看到

CommandText:

declare

type refcursortype is ref cursor;

begin

INSERT INTO z3 (test, id) VALUES (:p2, :p3);

:r1_4 := sql%rowcount;

end;

?

這里的p2就是我們的Clob類型字段的參數啦。

再看p2的OracleType是NVarChar,是不是有點明白啦,對了, 跟我們3一樣,參數類型錯掉了。

?

?

?

解決辦法:

?? 使用 NHibernate 的自定義類型,不是太會,幸好網上有高人提供代碼,在此想高人致謝。這樣我們通過自定義類型來設置正確的OracleType即可。在項目中添加兩個類。

?? PatchForOracleLobField.cs

  1. using?System;
  2. using?System.Collections.Generic;
  3. using?System.Data;
  4. using?System.Text;
  5. using?NHibernate;
  6. using?NHibernate.SqlTypes;
  7. using?NHibernate.UserTypes;
  8. namespace?Test.type
  9. {
  10. ????public?abstract?class?PatchForOracleLobField?:?IUserType
  11. ????{
  12. ????????public?PatchForOracleLobField()
  13. ????????{
  14. ????????}
  15. ????????public?bool?IsMutable
  16. ????????{
  17. ????????????get?{?return?true;?}
  18. ????????}
  19. ????????public?System.Type?ReturnedType
  20. ????????{
  21. ????????????get?{?return?typeof(String);?}
  22. ????????}
  23. ????????public?SqlType[]?SqlTypes
  24. ????????{
  25. ????????????get
  26. ????????????{
  27. ????????????????return?new?SqlType[]?{?NHibernateUtil.String.SqlType?};
  28. ????????????}
  29. ????????}
  30. ????????public?object?DeepCopy(object?value)
  31. ????????{
  32. ????????????return?value;
  33. ????????}
  34. ????????public?new?bool?Equals(object?x,?object?y)
  35. ????????{
  36. ????????????return?x?==?y;
  37. ????????}
  38. ????????public?int?GetHashCode(object?x)
  39. ????????{
  40. ????????????return?x.GetHashCode();
  41. ????????}
  42. ????????public?object?Assemble(object?cached,?object?owner)
  43. ????????{
  44. ????????????return?DeepCopy(cached);
  45. ????????}
  46. ????????public?object?Disassemble(object?value)
  47. ????????{
  48. ????????????return?DeepCopy(value);
  49. ????????}
  50. ????????public?object?NullSafeGet(IDataReader?rs,?string[]?names,?object?owner)
  51. ????????{
  52. ????????????return?NHibernate.NHibernateUtil.StringClob.NullSafeGet(rs,?names[0]);
  53. ????????}
  54. ????????public?abstract?void?NullSafeSet(IDbCommand?cmd,?object?value,?int?index);
  55. ????????public?object?Replace(object?original,?object?target,?object?owner)
  56. ????????{
  57. ????????????return?original;
  58. ????????}
  59. ????}
  60. }

?

OracleClobField.cs

  1. using ?System;
  2. using ?System.Collections.Generic;
  3. using ?System.Data;
  4. using ?System.Data.OracleClient;
  5. using ?System.Text;
  6. namespace ?Test.type
  7. {
  8. ????public?class?OracleClobField?:?PatchForOracleLobField
  9. ????{
  10. ????????public?override?void?NullSafeSet(IDbCommand?cmd,?object?value,?int?index)
  11. ????????{
  12. ????????????if?(cmd?is?OracleCommand)
  13. ????????????{
  14. ????????????????//CLob、NClob類型的字段,存入中文時參數的OracleDbType必須設置為OracleDbType.Clob
  15. ????????????????//否則會變成亂碼(Oracle?10g?client環境)
  16. ????????????????OracleParameter?param?=?cmd.Parameters[index]?as?OracleParameter;
  17. ????????????????if?(param?!=?null)
  18. ????????????????{
  19. ????????????????????param.OracleType?=?OracleType.Clob;// 關鍵就這里啦
  20. ????????????????????param.IsNullable?=?true;
  21. ????????????????}
  22. ????????????}
  23. ????????????NHibernate.NHibernateUtil.StringClob.NullSafeSet(cmd,?value,?index);
  24. ????????}
  25. ????}
  26. }

?

然后在映射文件中修改類型即可。

Com.Dic.Icqs.Entities.Type.OracleClobField,Com.Dic.Icqs.Entities

修改前:

<property column="test" type="StringClob" name="Test" length="2147483647" />

修改后:

<property column="test" type="Test.type.OracleClobField, Test " name="Test" length="2147483647" />

Test.type.OracleClobField是類的完整名,Test 即OracleClobField所在的程序集。

?

?

Oracle中Clob類型處理解析


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 亚洲一区二区三区四区热压胶 | 奇米影视亚洲 | 青青青爽视频在线观看 | 欧美极品福利视频在线播放 | 精品一区二区三区免费观看 | 久久精品一 | 国产精品久久久久久久久免费hd | 精品网站 | 四虎影视884a精品国产古代 | 国产美女久久 | 一级aaa级毛片午夜在线播放 | 国产成人亚洲精品乱码在线观看 | 日本三级不卡 | 奇米888四色在线精品 | 成人影院在线观看 | 亚洲欧美网址 | 黄色天堂在线 | 99热这里只有精品在线播放 | 久久久久免费精品视频 | 九九影院韩国理伦片 | 99免费在线视频 | 九九热视频免费 | 这里只有精品免费视频 | 中文字幕福利视频 | 91亚洲精品福利在线播放 | 国产美女流白浆的免费视 | 亚洲成年网 | 97视频免费上传播放 | 四虎永久免费地址在线观看 | 久夜色精品国产一区二区三区 | 免费 高清 日本1在线观看 | 久久国产热 | 精品久久洲久久久久护士 | 亚洲欧洲精品成人久久曰 | 国产色啪午夜免费视频 | 国产精品久久久久精 | 人人爱天天做夜夜爽2020麻豆 | 91青娱国产 | 亚洲欧洲精品视频在线观看 | 99精品视频免费在线观看 | 欧美亚洲国产成人精品 |