[seasar-dotnet:696] Oracle にて Insert 文でシーケンスを使った ID の生成について
Atsushi Kondou
[E-MAIL ADDRESS DELETED]
2007年 12月 15日 (土) 12:48:19 JST
いつもお世話になっております。
近藤です。
この度、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 メーリングリストの案内