2010年07月19日

DataSetデザイナーで「列には有効なDataTypeが必要です」のエラー

型付DataSet の プロパティの型を、独自に定義したenum型に変更していたのだけれど、
プログラムを修正していたら、いつのまにか、DataTypeが
「列には有効なDataTypeが必要です。」
というエラーメッセージが出て、DataSetデザイナーが開かなくなってしまいました。

初めは、どこが悪いのかまったくわからず Visual Studio 2008を起動しなおしたり、
DataSet.xsd をソース管理から再取得したりしましたが、エラーは出続けたままです。

いろいろ調べて、xxxxDataSet.xsd ファイル(これは、xmlファイルです)の


の部分が正しくないことに気がつきました。
リファクタリングで、このAbcEnum 型が定義されているプロジェクトを、別のプロジェクトに移したのが原因でした。

DataSetデザイナーが、AbcEnumの型を読み込もうとしても、指定したアセンブリには、その AbcENum型は存在しないので、

「列には有効なDataTypeが必要です。」

というエラーになっているようでした。
xxxxDataSet.xsd の中身を手で書き直すことで、無事DataSetデザイナーを開くことが出来ました。
  

Posted by gushwell at 23:20Comments(0)TrackBack(0)

2007年06月06日

TableAdapterのベースクラス

ずいぶん前だが、
C#のパーシャルクラスとデザイナが生成したコードについて考えてみる

という記事の中で、 「なちゃさん」から
---
TableAdapterは、デザイナでBaseClassプロパティで基底クラスを指定できる
--
ということを教えていただきました。

いままで確かめてみる機会がありませんでしたが、やっと利用する機会が出てきました。

これを使えば、いくつもある TableAdapter で同じコードを書く必要がなくなります。

以下、書いてみたコードの断片。


 public abstract class AbstractTableAdatpter : Component {
private const string FieldNameCommandCollection = "_commandCollection";

private SqlCommand[] CommandCollection {
get {
Type type = this.GetType();
FieldInfo field = type.GetField(FieldNameCommandCollection,
BindingFlags.NonPublic | BindingFlags.Instance);
SqlCommand[] array = (SqlCommand[])field.GetValue(this);
return array;
}
}

// 上記 CommandCollectionを使って、実装
// タイムアウト値の取得と設定を行う。
public int CommandTimeout {
get { ... }
set { ... ]
}
...
}

_adapter フィールドや、_connection フィールドも同じようにしてやれば、
いろんなことが共通化出来そうです。

ただ、まだ動かしていないので、正しく動くかどうかわかりません...
  
Posted by gushwell at 20:51Comments(0)TrackBack(0)

2007年05月31日

DataSetのカラムで列挙型を扱うには

型付DataSetのテーブルのカラムの型を、int ではなく、独自の列挙型にするには、2つの方法がある。

ひとつは、型付DataSetの定義を行う場合に列のデータ型を列挙型に指定する方法。
これは、デザイナー画面で、DataTypeプロパティの値を System.Int32 などから、独自の型 Gushwell.Genderなどを指定してあげればよい。
ドロップダウンリストには現れないので、手入力になる。

もうひとつは、partial クラスを使う方法。

型付DataRowクラスの partialクラスを作成し、その中に、列挙子用のプロパティを定義し、データ変換コードを書けばよい。

例えば、Gender というカラムがあった場合、

public partial class MyRow : System.Data.DataRow {
public Gender EnumGender {
get {
try {
return (Gender)(this.Gender);
} catch {
return Gender.Unknown;
}
}
set {
this.Gender = (int)value;
}
}
}

のように書けば良い。C#からは、Genderカラムではなく、EnumGenderカラムを参照するようにする。こうすることで、間接的ではあるが、DBのカラムを列挙型として扱うことができる。

後者のやり方は、try-catchで例外処理を記述できるのがメリット。
  
Posted by gushwell at 21:38Comments(0)TrackBack(0)

2007年05月10日

制約を有効にできませんでした。行に入力できるのは、Null 以外の値...

C#で、型付DataSetを使ったプログラムをデバッグしていたら、

「制約を有効にできませんでした。行に入力できるのは、Null 以外の値、一意な値、あるいは外部キーですが、この制約の違反が 1 つ以上の行で発生しています。」

というエラーが出るようになった。
なんで??

何のことはない、DataTableの カラムのプロパティが間違っていたのだが、この間違いに気が付くのに結構時間がかかってしまった。

具体的には、MaxLengthの長さが実際よりも短かった。。。
途中で、スキーマを変更したときに、こっちを変更するのを忘れていたみたい。

一生懸命 Null制約と外部キー制約あたりを調べていて、どこもおかしなところは無いのに、と見当ちがいの場所を調べていた orz
  
Posted by gushwell at 21:42Comments(2)

2006年07月13日

TableAdapter で Command のタイムアウトを設定するには

 public partial class MyTableAdapter {
public int CommandTimeout {
get {
return ( this.CommandCollection[0].CommandTimeout );
}

set {
for ( int i = 0; i < this.CommandCollection.Length; i++ ) {
if ( ( this.CommandCollection[i] != null ) ) {
( (System.Data.SqlClient.SqlCommand)
( this.CommandCollection[i] ) ).CommandTimeout = value;
}
}
}
}
}

C#2.0の新機能である partial クラスを使い、CommandTimeout プロパティを新設すれば、外から Timeout を設定できる。
でも、TableAdapterの数だけ、コーディングしなければいけないのは、気に入らない。
良い方法がないかな。

ちなみに、ネットのあるページでは、CommandCollection ではなく、