DBLinq(to Oracle)でトリガのカラム名が取得できない(ODP.NET)
DBLinqには"DBMetal"という、データベースのスキーマからエンティティのコンテキストクラス(LINQ to SQLのDataContextクラスに相当する)のソースコードを自動生成するツールが添付されてくるのだが、この"DBMetal"でOracle XEのエンティティを生成する際に、ODP.NETを使うと不具合が発生する。
生成するエンティティクラスのアトリビュートを設定するために、スキーマから制約を取得するのだが、その際にトリガ※のカラム名が取得できなくて例外(InvalidOperationException)が発生するのだ。
※Oracle(XE)上ではカラム名をIdとしてシーケンスにしており、トリガで実装されている
- DbLinq.Oracle.OracleSchemaLoader#LoadConstraints
else if (constraint.ConstraintType == "T" ) { //ODP.NETの場合、constraint.ColumnNameはnullで戻る(MSORACLEの場合、カラム名が取得できる) var column = table.Type.Columns.Where(c => c.Name == constraint.ColumnName).First(); column.Expression = constraint.Expression; column.IsDbGenerated = true; }
自らパッチを当てる前にtrunc上のコードを見てみると、既にパッチが当たっており、カラム名が取得できない場合はトリガの情報を収集しないように修正されていた。
- DbLinq.Oracle.OracleSchemaLoader#LoadConstraints (/svn/trunk/src/DbLinq.Oracle/OracleSchemaLoader.cs)
else if (constraint.ConstraintType == "T" && constraint.ColumnName != null) { var column = table.Type.Columns.Where(c => c.Name == constraint.ColumnName).First(); column.Expression = constraint.Expression; column.IsDbGenerated = true; }
OracleSchemaLoader.cs - dblinq2007 - Project Hosting on Google Code
こうすると例外は防げるが、本来、以下のように付加されるエンティティクラスのカラムへのプロパティにトリガの情報が抜けてしまうのである。
- 生成されるAddressBookクラスのIdプロパティ
private decimal _id; [DebuggerNonUserCode] [Column(Storage = "_id", Name = "ID", DbType = "NUMBER", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false, Expression = "\"ADDRESSBOOK_SEQ\".nextval")] public decimal ID { 〜 }
トリガ情報を取得することにより以下の式情報が属性に追加されるのだ。
Expression = "\"ADDRESSBOOK_SEQ\".nextval")
テストしてみないとどちらが正しいか分らないんだが、ADO.NETプロバイダの違いによって、同じプロパティの表現が違うのはまずいだろうな。
弄りだして数時間で既に幾つか問題点が発生しているのを見ると、やはりまだ仕事で使える類のものではなさそうだ。
今更NHibernateとかiBATIS等のORMも使いたくないし、かといって商用のプロバイダに$300かけるのもなぁ。
やっぱり今回はSQLServer使わせてくれよー。