[seasar-dotnet:711] Re: Oracle にて Insert 文でシーケンスを使った ID の生成について

koyak [E-MAIL ADDRESS DELETED]
2007年 12月 23日 (日) 23:10:40 JST


近藤様

小谷です。

ソースコードを修正し、動作の確認ができたのでコミット致しました。
遅くなってしまい、大変申し訳ありませんでした。

修正の正式な反映は1.3.6になるかと思いますが、
お急ぎの場合は
https://www.seasar.org/svn/s2container.net/trunk/s2container.net/source
下のソースコードをコンパイルしてご使用下さい。

07/12/19 に Atsushi   Kondou<[E-MAIL ADDRESS DELETED]> さんは書きました:
> 小谷様
>
> 遅くなってすみません。近藤です。
> 回答ありがとうございます。
> 修正がコミットされ次第1.3.5の検証を行おうと思います。
>
> よろしくお願いします。
>
> --- koyak <[E-MAIL ADDRESS DELETED]> wrote:
>
> > 近藤様
> >
> > 小谷です。
> >
> > 詳細なご連絡ありがとうございます。
> >
> > S2Container.NET 1.3.5からInsert時にnullの列をinsert文に含まないようにする
> > 修正を行っているのですが、この修正が原因と思われます。
> > 大変申し訳ありません。
> >
> > 解決方法についてですが、
> > Seasar.Dao.Impl.InsertAutoDynamicCommandのIsTargetPropertyを
> > 以下のように書き換えてみていただけないでしょうか。
> >
> > protected override bool IsTargetProperty(IPropertyType pt, string
> > timestampPropertyName, string versionNoPropertyName, object bean)
> > {
> >     IIdentifierGenerator identifierGenerator = BeanMetaData.IdentifierGenerator;
> >     if (pt.IsPrimaryKey)
> >     {
> >         return identifierGenerator.IsSelfGenerate;
> >     }
> >     return base.IsTargetProperty(pt, timestampPropertyName,
> > versionNoPropertyName, bean);
> > }
> >
> > 元のコードではRDBMSのIDENTITYを使用している列をi
> > nsert文に含めないようにしています。
> > (insert時に自動的にRDBMSの方でIDが割り振られるため)
> >
> > シーケンスの場合はIDENTITYと違いinsert文に列を含める必要があるのですが
> > これを含める処理が抜けていました。
> >
> > こちらの環境で検証ができ次第修正したソースをコミットしたいと思います。
> > ご迷惑をおかけしました。
> >
> > --------------------------------------------------------
> > koyak
> > mail:[E-MAIL ADDRESS DELETED]
> > --------------------------------------------------------
> >
> >
> >
> > 07/12/15 に Atsushi  Kondou<[E-MAIL ADDRESS DELETED]> さんは書きました:
> > > いつもお世話になっております。
> > > 近藤です。
> > >
> > > この度、S2Container.NET 1.3.0で稼動していたシステムをS2Container.NET
> > 1.3.5にバージョンをあげたところ
> > > INSERT文が失敗するようになりました。
> > >
> > > Insert文でシーケンスを使ったIDの生成の際IDが無視されたSQLが生成されるようです
> > >
> > > 自分なりに調査をした結果を報告します。
> > > 解決策がお分かりでしたらをご教授下さい。
> > > よろしくお願いします。
> > >
> > >
> > > 環境:
> > > OS:Windows Vista
> > > DB:Oracle10g
> > > IDE:Visual Studio 2005 SP1
> > > 言語:C#
> > >
> > >
> > > Entityクラスの抜粋
> > > [Table("COMPANIES"), TimestampProperty("UpdateDate")]
> > > public class Company {
> > > /*Company.cs*/
> > >   [Column("ID"), ID(IDType.SEQUENCE, "COMPANIES_ID_SEQ",KindOfDbms.Oracle)]
> > >   public long? Id{
> > >     ・・・
> > >   }
> > >   public long? Code{
> > >     ・・・
> > >   }
> > >   public String Name{
> > >     ・・・
> > >   }
> > >   public DateTime UpdateDate{
> > >     ・・・
> > >   }
> > > }
> > > DAOクラスの抜粋
> > > [Bean(typeof(Company))]
> > > public interface ICompanyDao {
> > >   void Insert(Company company);
> > > }
> > >
> > > 1)生成されたSQL文でIDが対象となっていないので
> > >   INSERT INTO COMPANIES (UPDATE_DATE, NAME, CODE) VALUES (?, ?, ?)
> > > が実行され以下の例外が発生する
> > > [ESSR0071]SQLで例外が発生しました。理由はSystem.Data.OracleClient.OracleException: ORA-01400:
> > > ("HOGE"."COMPANIES"."ID")
> > > にはNULLは挿入できません。
> > >    場所 System.Data.OracleClient.OracleConnection.CheckError(OciErrorHandle errorHandle, Int32
> > rc)
> > >    場所 System.Data.OracleClient.OracleCommand.Execute(OciStatementHandle statementHandle,
> > > CommandBehavior behavior, Boolean needRowid, OciRowidDescriptor& rowidDescriptor, ArrayList&
> > > resultParameterOrdinals)
> > >    場所 System.Data.OracleClient.OracleCommand.ExecuteNonQueryInternal(Boolean needRowid,
> > > OciRowidDescriptor& rowidDescriptor)
> > >    場所 System.Data.OracleClient.OracleCommand.ExecuteNonQuery()
> > >    場所 Seasar.Framework.Util.CommandUtil.ExecuteNonQuery(IDataSource dataSource, IDbCommand
> > cmd) 場
> > > 所 E:\csharp\s2container.net\source\Seasar\Seasar.Framework.Util\CommandUtil.cs:行 66
> > >
> > > 2)SetIdentifierではシーケンスを使ってIDは生成されるのを確認しました。
> > >
> > > 3)この箇所が原因みたいなのですがどう解釈すれば良いのかわかりません。
> > > Seasar.Dao.Impl::AbstractAutoDynamicCommandのCreateTargetPropertyTypes
> > > Seasar.Dao.Impl::InsertAutoDynamicCommand
> > > Seasar.Dao.Impl::AbstractAutoDynamicCommandのIsTargetProperty
> > > object value = pt.PropertyInfo.GetValue(bean, null);
> > > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > ここでIDの場合valueがnullなのでfalseが返る
> > > if(value == null)
> > > {
> > >     return false;
> > > }
> > >
> > >
> > 4)Seasar.Dao.Impl::AbstractAutoHandlerで_bindVariablesのインスタンス変数でIDが対象外になっている
> > > Execute
> > >   PreUpdateBean(bean);←beanのIDには生成されたIDが含まれている
> > >   SetupBindVariables(bean);
> > >   └Seasar.Dao.Impl::InsertAutoHandler::SetupBindVariables
> > >       SetupInsertBindVariables(bean);
> > >       └インスタンス変数の_propertyTypesにはIDが除かれている
> > >
> > > 以上
> > > _______________________________________________
> > > seasar-dotnet mailing list
> > > [E-MAIL ADDRESS DELETED]
> > > https://ml.seasar.org/mailman/listinfo/seasar-dotnet
> > >
> >
>
>


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