3. サンプルアプリケーション
ひとまず、本家サイトのソースを載せます。
using System; using System.IO; using Examples.FirstProject.Entities; using FluentNHibernate.Cfg; using FluentNHibernate.Cfg.Db; using NHibernate; using NHibernate.Cfg; using NHibernate.Tool.hbm2ddl; namespace Examples.FirstProject { class Program { private const string DbFile = "firstProgram.db"; static void Main() { var sessionFactory = CreateSessionFactory(); using (var session = sessionFactory.OpenSession()) { using (var transaction = session.BeginTransaction()) { // create a couple of Stores each with some Products and Employees var barginBasin = new Store { Name = "Bargin Basin" }; var superMart = new Store { Name = "SuperMart" }; var potatoes = new Product { Name = "Potatoes", Price = 3.60 }; var fish = new Product { Name = "Fish", Price = 4.49 }; var milk = new Product { Name = "Milk", Price = 0.79 }; var bread = new Product { Name = "Bread", Price = 1.29 }; var cheese = new Product { Name = "Cheese", Price = 2.10 }; var waffles = new Product { Name = "Waffles", Price = 2.41 }; var daisy = new Employee { FirstName = "Daisy", LastName = "Harrison" }; var jack = new Employee { FirstName = "Jack", LastName = "Torrance" }; var sue = new Employee { FirstName = "Sue", LastName = "Walkters" }; var bill = new Employee { FirstName = "Bill", LastName = "Taft" }; var joan = new Employee { FirstName = "Joan", LastName = "Pope" }; // add products to the stores, there's some crossover in the products in each // store, because the store-product relationship is many-to-many AddProductsToStore(barginBasin, potatoes, fish, milk, bread, cheese); AddProductsToStore(superMart, bread, cheese, waffles); // add employees to the stores, this relationship is a one-to-many, so one // employee can only work at one store at a time AddEmployeesToStore(barginBasin, daisy, jack, sue); AddEmployeesToStore(superMart, bill, joan); // save both stores, this saves everything else via cascading session.SaveOrUpdate(barginBasin); session.SaveOrUpdate(superMart); transaction.Commit(); } // retreive all stores and display them using (session.BeginTransaction()) { var stores = session.CreateCriteria(typeof(Store)) .List(); foreach (var store in stores) { WriteStorePretty(store); } } Console.ReadKey(); } } private static ISessionFactory CreateSessionFactory() { return Fluently.Configure() .Database(SQLiteConfiguration.Standard .UsingFile(DbFile)) .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Program>()) .ExposeConfiguration(BuildSchema) .BuildSessionFactory(); } private static void BuildSchema(Configuration config) { // delete the existing db on each run if (File.Exists(DbFile)) File.Delete(DbFile); // this NHibernate tool takes a configuration (with mapping info in) // and exports a database schema from it new SchemaExport(config) .Create(false, true); } private static void WriteStorePretty(Store store) { Console.WriteLine(store.Name); Console.WriteLine(" Products:"); foreach (var product in store.Products) { Console.WriteLine(" " + product.Name); } Console.WriteLine(" Staff:"); foreach (var employee in store.Staff) { Console.WriteLine(" " + employee.FirstName + " " + employee.LastName); } Console.WriteLine(); } public static void AddProductsToStore(Store store, params Product[] products) { foreach (var product in products) { store.AddProduct(product); } } public static void AddEmployeesToStore(Store store, params Employee[] employees) { foreach (var employee in employees) { store.AddEmployee(employee); } } } }
(Program.cs)
Main関数内では、
- 2つのStore
- 6つのProduct
- 5人のEmployee
を生成し、それぞれをStoreに追加し保存、次に保存先から読みだして表示する。という構成になっています。
ここでは、サンプルのままなのでSQLiteでの設定になっていますが、後程PostgreSQL用に変更します。
Configuration
NHibernate用のセッション管理用の実装をします。ここに、データベースへの接続情報等が入力されます。
ここでは、サンプルのCreateSessionFactoryをSQLite仕様からPostgreSQL仕様に変更します。
前提として
- localhostのPostgreSQL 9.1.1
- ポートはデフォルトの5432
- データベースはtestdb(スキーマはなくても、既に存在する)
- ユーザ名は「postgres」
- パスワードは「postgres」
とすると、以下のように変更します。
private static ISessionFactory CreateSessionFactory() { return Fluently.Configure() .Database(PostgreSQLConfiguration.PostgreSQL82 .ConnectionString(x => x .Host("localhost") .Port(5432) .Database("testdb") .Username("postgres") .Password("postgres"))) .Mappings(m => m .FluentMappings.AddFromAssemblyOf<Program>()) .ExposeConfiguration(BuildSchema) .BuildSessionFactory(); }
利用したPostgreSQLは9.1.1でしたが、8.2用で動くみたいです。(というより、8.1か8.2しか選べない)
今回はMappings()内で
AddFromAssemblyOf<Program>()
を呼びましたが、マッピングクラスを個別に呼ぶ場合は
using Examples.FirstProject.Mappings; // 追加 .Mappings(m => m .FluentMappings.AddFromAssemblyOf<ProductMap>() .AddFromAssemblyOf<EmployeeMap>() .AddFromAssemblyOf<StoreMap>() )
と、記述してください。
あとは、データベーススキーマ(テーブル)を作成するBuildSchemaの中のFile.Delete()のif文をコメントアウトすれば、実行可能です。
private static void BuildSchema(Configuration config) { // delete the existing db on each run //if (File.Exists(DbFile)) // File.Delete(DbFile); // this NHibernate tool takes a configuration (with mapping info in) // and exports a database schema from it new SchemaExport(config) .Create(false, true); }
実行前に、テーブルは無くてもいいのでtestdbは用意しておいてください。
また、ExposeConfiguration(BuildSchema)を呼ぶと毎回リセットされるので注意してください。(リセットしたくない場合はこの行をコメントアウトしてください)
実行前
実行結果
実行後