[seasar-dotnet:1559] Re: [DBFlute.NET][S2Container.NET] IDbDataParameter の DbType を変更する場合

kubo [E-MAIL ADDRESS DELETED]
2010年 2月 16日 (火) 15:09:46 JST


久保(jflute)です。

なるほど、詳しい状況ありがとうございます。
なんとも最高にややこしい状況ですねぇ。

まとめると:

S2Dao.NET、DBFlute.NET共にデフォルトで
DbType.Stringを利用する。すると、
DBがSJISでVARCHARの場合に全角TILDE問題発生。

A. DBのキャラセットをJA16SJISTILDE使う
B. DBのキャラセットをUTF-8にする
C. VARCHARだけ利用なら一律DbType.AntiStringに設定

で回避ができるが、JA16SJISTILDEが利用できず、
(SJISで)VARCHARとNVARCHAR混在システムだとつらい。

ということで、本来的にはDBFlute.NETでは
VARCHARの時とNVARCHARの時はValueTypeを
切り替えて利用出来るようにした方が良いということに
なりますね。(今はString型に対して、という判定)

どちらか片方のマッピングの型をStringじゃなくて、
独自のString型とかにすれば今でも対応できそうですが、
それはあまりに現実的じゃなさ過ぎますね。
ValueType属性を使って、NVARCHARだけValueTypeを
差し変えるようにテンプレートレベルで工夫するとか。
いずれにせよ根本的な対応のポリシーはもう少し練る
必要がありそうですね。(きっちり対応するのか、
テンプレートの修正でお願いするかなども含めて)

とりあえず、次のバージョンでは、"C" がやりやすいように
DBFluteConfigで設定できるようにしました。
但し、プロシージャに関しては、ValueTypeの
リファクタリングが必要で、対応はもっと先になるかなと。

色々、整理するきっかけになりました。
情報提供ありがとうございました。

2010/2/16 西山 はじめ <[E-MAIL ADDRESS DELETED]>:
> 西山(hajimeni)です。
>
> アプリ内では、文字列は全てVARCHAR2です。
> よって、一律DbType.AnsiStringを利用することにします。
>
> NVARCHARは利用していた場合、NVARCHARにはDbType.String、 VARCHAR2にはDbType.AnsiString
> を指定しないとダメではないかと。
>
> 利用しているDataProviderでは次のように動作します。
>
> 1.DbType.Stringを指定した場合。
> 内部でNVARCHARと判断し、NLS_NCHAR_CHARACTERSET(デフォルトは
> AL16UTF16)にエンコード変換してからデータベースに送信。
>
> クライアント(.NET):0xFF5E(UTF)
>> DataProvider内:0xFF5E(UTF)
>> ×一致しない!
>> Oracl内部変換:0x301C(UTF)
>> Oracleデータ(VARCHAR2):0x8160(SJIS)
>
> 2.DbType.AnsiStringを指定した場合
> 内部でVARCHAR2と判断し、NLS_CHARACTERSET(今回の場合、 JA16SJIS)の文字列にエンコードしてからデータベースに送信。
>
> クライアント(.NET):0xFF5E(UTF)
>> DataProvider内:0x8160(SJIS)
>> ○一致する
>> Oracleデータ(VARCHAR2):0x8160(SJIS)
>
> となり、2の方だとOracle内で文字コードの変換が発生しないた め、問題が発生しなくなります。
> (サポートからの情報を元にした推測の動作です)
>
> また、このDataProvider、「~」の変換を文字化けしないように行 なってしまう為、パッと見気づきにくいです。
> (あと、Likeの時だけ再現しないとか他にも色々あるのですが・・・)
>
> ちなみに、ODP.NETの場合は、 DbType.Stringを指定した場合、 「正しく文字化け(この言い方もおかしいですが)」します。
>
>
>
> [2010/02/16 13:11] kubo さんは書きました。:
>>
>> 久保(jflute)です。
>>
>>> JA16SJISTILDEです。それは把握しております。
>>> 可能ならばそちらにしたいのですが、同じDBに相乗りしているシステムがOracle8iクライアントを利用していまして・・・
>>> Oracle8iクライアントから、
>>>
>>> Oracle9iサーバーのJA16SJISTILDEに接続すると、レスポンス速度が著しく悪くなるという現象がありまして、JA16SJISにしてアプリで対応せざるを得ないという状況です。
>>> (8iには~TILDEがありませんので当然と言えば当然ですが・・・むしろ動く方がびっくり)
>>
>> そんな現象が...
>> ありがとうございます。
>>
>> TILDEが発生するのはVARCHARだけで、
>> NVARCHARでは発生していない、でOKでしょうか?
>> また、一律AnsiStringを利用するに設定しても
>> NVARCHARの処理に特に問題はないでしょうか?
>> (そもそもアプリでNVARCHAR使ってないならいいです。
>> もし、すぐにわかるレベルであれば教えて頂ければと)
>>
>> 2010/2/16 西山はじめ<[E-MAIL ADDRESS DELETED]>:
>>>
>>> 西山(hajimeni)です。
>>>
>>> 回答ありがとうございます。
>>>
>>>> StringTypeに関しては、アプリ起動時に
>>>> ValueTypes.RegisterValueType()で差し替えが可能かも。
>>>
>>> そんな機能があったのですね。試してみます。
>>>
>>>> InternalProcedureHandlerに関しては、現状では
>>>> テンプレートを直すしか方法はないです。
>>>
>>> 了解いたしました。
>>>
>>>> JA16SJISじゃなくて、全角チルダ問題を回避するための
>>>> Oracleが提供するSJISのエンコーディングってありません
>>>> でしたっけ?それを使って回避できないのかなと。
>>>> (今回の件で適用できるかどうかは別にして)
>>>
>>> JA16SJISTILDEです。それは把握しております。
>>> 可能ならばそちらにしたいのですが、同じDBに相乗りしているシステムがOracle8iクライアントを利用していまして・・・
>>> Oracle8iクライアントから、
>>>
>>> Oracle9iサーバーのJA16SJISTILDEに接続すると、レスポンス速度が著しく悪くなるという現象がありまして、JA16SJISにしてアプリで対応せざるを得ないという状況です。
>>> (8iには~TILDEがありませんので当然と言えば当然ですが・・・むしろ動く方がびっくり)
>>>
>>> ///
>>> /// 本当はDBのCharsetはUTFにしたいのですが・・・
>>> ///
>>>
>>> 2010年2月16日11:52 kubo<[E-MAIL ADDRESS DELETED]>:
>>>>
>>>> 久保(jflute)です。
>>>>
>>>> 西山さん、こんにちは
>>>>
>>>> 自分も確証があるわけではないですが、
>>>> 把握してる限りで、そのニ箇所ですね。
>>>> プロシージャだけ特別ですが、あとは
>>>> 基本StringTypeを直してしまえば他全ての処理で
>>>> そのようになるはずです。
>>>>
>>>> StringTypeに関しては、アプリ起動時に
>>>> ValueTypes.RegisterValueType()で差し替えが可能かも。
>>>> InternalProcedureHandlerに関しては、現状では
>>>> テンプレートを直すしか方法はないです。
>>>>
>>>> 後学のために:
>>>>
>>>> JA16SJISじゃなくて、全角チルダ問題を回避するための
>>>> Oracleが提供するSJISのエンコーディングってありません
>>>> でしたっけ?それを使って回避できないのかなと。
>>>> (今回の件で適用できるかどうかは別にして)
>>>>
>>>> もし、NOだとすると、
>>>> データプロバイダ次第で、DbTypeを調整する必要があるって
>>>> のはちょっと色々と不都合があるので改善が必要かもですね。
>>>> (NVarcharか否かを判定して、内部で自動でStringTypeを
>>>> 切り替えるとか...逆にどのデータプロバイダでもそれで
>>>> OKならわかりやすいのですが、データプロバイダごとに
>>>> 最適な方法が変わるとつらいですね)
>>>>
>>>>
>>>> 2010/2/16 西山はじめ<[E-MAIL ADDRESS DELETED]>:
>>>>>
>>>>> 西山(hajimeni)です。
>>>>> お世話になっております。
>>>>>
>>>>> DBFlute.NET利用時に、IDbDataParameter の DbType を変更する場合、次の箇所を直せば大丈夫でしょうか。
>>>>> String型の時だけ DbType.String ではなく、 DbType.AnsiString を指定したいと思っています。
>>>>>
>>>>> ・Seasar.Extension.ADO.Types.StringTypeのBindValueメソッドを次のように変更。
>>>>> BindValue(cmd, columnName, value, DbType.AnsiString);
>>>>>
>>>>>
>>>>> ・Sample.DBFlute.AllCommon.S2Dao.Internal.SqlHandler.InternalProcedureHandler
>>>>> のGetDbValueType内のメソッドを変更。
>>>>> ・・・(略)
>>>>> if (type == typeof(String) || type.FullName == "System.String&")
>>>>>    return DbType.AnsiString;
>>>>> ・・・(略)
>>>>>
>>>>> 環境は次のとおりです。
>>>>> Oracle9i(9.2.0.6)
>>>>>  (文字コード:JA16SJIS)
>>>>> S2Container.NET 1.3.16.1
>>>>> DBFlute.NET 0.8.9.2
>>>>>
>>>>> というのも、どうやらOracleとの接続に利用しているサードパーティ製のdllでは、
>>>>> DbType.AnsiString → Varchar
>>>>> DbType.String → NVarchar
>>>>> と解釈するため、データベースの文字コードが「JA16SJIS」の場合、「~」が上手く検索出来ない(いわゆる全角チルダ問題)
>>>>> が発生してしまいます。
>>>>> DbType.String を指定した場合、単純に検索した結果が文字化けするのではなく、検索結果そのものが存在しなくなってしまいます。
>>>>>
>>>>> 回避策はどうやら、DbType.AnsiString を指定するしかないとのことです。
>>>>>
>>>>> 出来れば、.NETのTypeと
>>>>> DbTypeのマッピングが変更出来ればよいのですが、割りと早めに修正しなければならない為、直接手をいれることにしました。
>>>>>
>>>>> 以上よろしくお願いいたします
>>>>> --
>>>>> --
>>>>> 西山はじめ
>>>>> _______________________________________________
>>>>> seasar-dotnet mailing list
>>>>> [E-MAIL ADDRESS DELETED]
>>>>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>>>>
>>>> _______________________________________________
>>>> seasar-dotnet mailing list
>>>> [E-MAIL ADDRESS DELETED]
>>>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>>>
>>>
>>>
>>>
>>> --
>>> --
>>> 西山はじめ
>>> _______________________________________________
>>> seasar-dotnet mailing list
>>> [E-MAIL ADDRESS DELETED]
>>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>>
>> _______________________________________________
>> seasar-dotnet mailing list
>> [E-MAIL ADDRESS DELETED]
>> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>>
>>
>>
>
>
> --
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 株式会社フジミック
>         システム開発センター ソフトウェア開発部
>  西山 創
> [E-mail]:[E-MAIL ADDRESS DELETED]
>
> 〒140-0002 東京都品川区東品川3-32-42 フジテレビ別館7階
> [TEL]:03-5495-1060
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>
> _______________________________________________
> seasar-dotnet mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/seasar-dotnet
>


seasar-dotnet メーリングリストの案内