SQLite の dbml
「System.Data.Sqlite、Linq」、「LINQ to SQL クラスの自動生成」から、既製品による自動生成は諦めることにします。作成するとして、何を生成すれば良いか確認して置きます。
1.プロジェクトの準備
- System.Data.SQLite を使います。インストールして置きます。
- WPF アプリケーション・プロジェクトを作ります。WpfApplication3 が出来ました。
- 「参照の追加」で、System.Data.SQLite、System.Data.SQLite.Linq を追加します。
- Window1.xaml の <Grid> に Loadedイベントを設定します。
- イベントハンドラを自動生成し、このハンドラに下記のテスト用のコードを書いて置きます。(この段階では、当然エラーになります。)
- private void Grid_Loaded(object sender, RoutedEventArgs e)
- {
- DataClasses1DataContext db = new DataClasses1DataContext();
- var rows2 = from t1 in db.Table_1 select new { t1.title, t1.Table_2.content };
- foreach (var o in rows2)
- Debug.WriteLine(o.title + " " + o.content);
- }
- もし、Windows x64 を使っているなら、「構成マネージャー」で「ソリューションプラットフォーム」を「Any CPU」から「x86」に変えておくことが必要です。
2.テストデータの用意
2つのテーブルがあり、表題(title)と本文(content)が別のテーブルにあります。content_id で繋がっています。
SQLite Database Browser.exe と言うソフトでデータベース、テーブルを作り、少しだけデータを入れて置きました。
左図は、これから作る dbml を Visual Studio で開いたときの表示です。
フィールドの型ですが、title と content は TEXT です。
idは、INTEGER PRIMARY KEY です。
content_id は、Table_1 が Numeric、Table_2 が INTEGER PRIMARY KEY です。
SQLite のデータベースは、TEXT、NUMERIC、BLOB,INTEGER PRIMARY KEY が識別されるだけで、型を持たない発想からできているようです。
データベースからテーブルの情報を取得すると、テーブルを生成した時のSQL文が返されます。
それ以上詳しい情報は無いようです。
3.dbml の作成
DataClasses1.dbml を以下の内容で作成しました。
- <?xml version="1.0" encoding="utf-8"?>
- <Database Name="sample" Class="DataClasses1DataContext" xmlns="http://schemas.microsoft.com/linqtosql/dbml/2007">
- <Connection Mode="ConnectionString" ConnectionString="DbLinqProvider=Sqlite; Data Source=sample.sqlite" SettingsObjectName="WpfApplication3.Properties.Settings" Provider="System.Data.Sqlite" />
- <Table Name="Table_1" Member="Table_1">
- <Type Name="Table_1">
- <Column Name="id" Type="System.Int64" DbType="BigInt NOT NULL" CanBeNull="false" />
- <Column Name="title" Type="System.String" DbType="NVarChar(50) NOT NULL" CanBeNull="false" />
- <Column Name="content_id" Type="System.Int64" DbType="BigInt NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
- <Association Name="Table_2_Table_1" Member="Table_2" ThisKey="content_id" OtherKey="content_id" Type="Table_2" IsForeignKey="true" />
- </Type>
- </Table>
- <Table Name="Table_2" Member="Table_2">
- <Type Name="Table_2">
- <Column Name="content_id" Type="System.Int64" DbType="BigInt NOT NULL" IsPrimaryKey="true" CanBeNull="false" />
- <Column Name="content" Type="System.String" DbType="NVarChar(MAX)" CanBeNull="true" />
- <Association Name="Table_2_Table_1" Member="Table_1" ThisKey="content_id" OtherKey="content_id" Type="Table_1" Cardinality="One" />
- </Type>
- </Table>
- </Database>
これは、ゼロから書いたわけではなく、SQL Server で、同じ形式のテーブルを作って、自動生成したものを修正しました。
変更は、最初の方の<Connection>の内容です。
フィールドの型がそれらしく入っていますが、前述の通り、SQLite には型がほとんどないのであまり意味がありません。
4.プロジェクトに追加
ソリューションエクスプローラの窓で、プロジェクトを選択し、右ボタンメニューから「追加」「既存の項目」で、DataClasses1.dbml を追加します。
自動的に、DataClasses1.designer.cs、DataClasses1.dbml.layout が生成されます。
これで、ビルドできるようになります。
ただし、1つだけ問題が残っています。
System.Data.Linq.DataContex のコンストラクタでは、SQLight のデータベースが開けないと言うものです。
接続文字列が指定された場合、プロバイダの指定があれば、それを使うのが予定の行動だと思うのですが、実際は SQLiteConnection を直接呼び出す必要があります。
方法は2つあります。1つは、DataClasses1.designer.cs を変更するもので、他方はテスト用のコードの修正です。
下記は、DataClasses1.designer.cs の最初の方にある、DataClasses1DataContext クラスのコンストラクタの1つ(引数なしのコンストラクタ)です。
- public DataClasses1DataContext() :
- base("DbLinqProvider=Sqlite; Data Source=sample.sqlite", mappingSource)
- {
- OnCreated();
- }
これを、以下のように修正します。これで、正常にテスト用のコードが実行できました。
- public DataClasses1DataContext() :
- base(new System.Data.SQLite.SQLiteConnection("DbLinqProvider=Sqlite; Data Source=sample.sqlite"), mappingSource)
- {
- OnCreated();
- }
また、DataClasses1.designer.cs を修正する代わりに、テスト用のコードを以下のように修正しても OK です。
コネクションを引数に持つ、コンストラクタを呼び出します。
- private void Grid_Loaded(object sender, RoutedEventArgs e)
- {
- System.Data.IDbConnection con
- =new System.Data.SQLite.SQLiteConnection("DbLinqProvider=Sqlite; Data Source=sample.sqlite");
- DataClasses1DataContext db = new DataClasses1DataContext(con);
- var rows2 = from t1 in db.Table_1 select new { t1.title, t1.Table_2.content };
- foreach (var o in rows2)
- Debug.WriteLine(o.title + " " + o.content);
- }
|