Nhibernate-data-types-mapping

提供:Dev Guides
移動先:案内検索

NHibernate-データ型マッピング

この章では、マッピングデータ型について説明します。 エンティティのマッピングは簡単で、エンティティクラスは常に <class>、<subclass>、および<joined-subclass> マッピング要素を使用してデータベーステーブルにマッピングされます。 値型にはさらに何かが必要です。マッピング型が必要な場所です。

NHibernateは、さまざまなデータタイプをマップできます。 以下は、サポートされている最も一般的なデータ型のリストです。

Mapping type .NET type System.Data.DbType
Int16 System.Int16 DbType.Int16
Int32 System.Int32 DbType.Int32
Int64 System.Int64 DbType.Int64
Single System.Single DbType.Single
Double System.Double DbType.Double
Decimal System.Decimal DbType.Decimal
String System.String DbType.String
AnsiString System.String DbType.AnsiString
Byte System.Byte DbType.Byte
Char System.Char DbType.StringFixedLength—one character
AnsiChar System.Char DbType.AnsiStringFixedLength—one character
Boolean System.Boolean DbType.Boolean
Guid System.Guid DbType.Guid
PersistentEnum System.Enum(an enumeration) DbType for the underlying value
TrueFalse System.Boolean DbType.AnsiStringFixedLength—either 'T' or 'F'
YesNo System.Boolean DbType.AnsiStringFixedLength—either 'Y' or 'N'
DateTime DateTime DbType.DateTime—ignores milliseconds
Ticks System.DateTime DbType.Int64
TimeSpan System.TimeSpan DbType.Int64
Timestamp System.DateTime DbType.DateTime—as specific as the database supports
Binary System.Byte[] DbType.Binary
BinaryBlob System.Byte[] DbType.Binary
StringClob System.String DbType.String
Serializable Any System.Object marked with SerializableAttribute DbType.Binary
CultureInfo System.Globalization.CultureInfo DbType.String—five characters for culture
Type System.Type DbType.String holding the Assembly Qualified Name

上記の表は、下記のポインターを詳細に説明しています。

  • 単純な数値型から文字列まで、すべて varchars、chars などを使用してさまざまな方法でマッピングできます。 文字列blob、およびデータベースがサポートするすべてのさまざまなタイプ。
  • また、ゼロと1を使用するフィールド、true、false、またはTとFを含む文字フィールドの両方に*ブール値*をマップすることもできます。
  • データベース内のバックエンド、ブール値にマップする方法を定義するさまざまな方法があります。
  • タイムゾーンオフセット、夏時間などを含めて、 DateTime のマッピングを処理できます。
  • *列挙*をマップすることもできます。これらを文字列または基になる数値にマップできます。

データベースとStudentクラスの両方で同じプロパティ名を使用する簡単な例を見てみましょう。

では、学生クラスでFirstMidNameをFirstNameに変更します。FirstMidName列は変更しませんが、NHibernateにこの変換を実行することを知らせる方法を確認します。 以下は、更新された学生クラスです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NHibernateDemoApp {

   class Student {
      public virtual int ID { get; set; }
      public virtual string LastName { get; set; }
      public virtual string FirstName { get; set; }
   }
}

NHibernateマッピングファイルの実装を次に示します。

<?xml version = "1.0" encoding = "utf-8" ?>
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2" assembly = "NHibernateDemoApp"
   namespace = "NHibernateDemoApp">

   <class name = "Student">

      <id name = "ID">
         <generator class = "native"/>
      </id>

      <property name = "LastName"/>
      <property name = "FirstName" column = "FirstMidName" type = "String"/>
   </class>

</hibernate-mapping>

この例では、FirstNameフィールドが.NET文字列で、FirstMidName列が SQL nvarchar であると想定しています。 NHibernateにこの変換の実行方法を伝えるには、名前を FirstName に、列を FirstMidName に設定し、この特定の変換に適したマッピングタイプをStringに指定します。

以下は Program.cs ファイルの実装です。

using HibernatingRhinos.Profiler.Appender.NHibernate;
using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Driver;

using System;
using System.Linq;
using System.Reflection;

namespace NHibernateDemoApp {

   class Program {

      static void Main(string[] args) {

         NHibernateProfiler.Initialize();
         var cfg = new Configuration();

         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;

         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source +
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover";

            x.Driver<SqlClientDriver>();
            x.Dialect<MsSql2008Dialect>();
            x.LogSqlInConsole = true;
         });

         cfg.AddAssembly(Assembly.GetExecutingAssembly());
         var sefact = cfg.BuildSessionFactory();

         using (var session = sefact.OpenSession()) {

            using (var tx = session.BeginTransaction()) {
               var students = session.CreateCriteria<Student>().List<Student>();
               Console.WriteLine("\nFetch the complete list again\n");

               foreach (var student in students) {
                  Console.WriteLine("{0} \t{1} \t{2}", student.ID, student.FirstName,
                     student.LastName);
               }

               tx.Commit();
            }

            Console.ReadLine();
         }
      }
   }
}

これで、アプリケーションを実行すると、次の出力が表示されます。

NHibernate: SELECT this_.ID as ID0_0_, this_.LastName as LastName0_0_,
   this_.FirstMidName as FirstMid3_0_0_ FROM Student this_

Fetch the complete list again
3 Allan Bommer
4 Jerry Lewis

ご覧のとおり、異なるプロパティ名がデータベースの列名にマッピングされています。

*enum* タイプのStudentクラスに別のプロパティを追加する別の例を見てみましょう。 これがStudentクラスの実装です。
using System;
using System.Collections.Generic;
using System.Linq; using System.Text;
using System.Threading.Tasks;

namespace NHibernateDemoApp {

   class Student {
      public virtual int ID { get; set; }
      public virtual string LastName { get; set; }
      public virtual string FirstName { get; set; }
      public virtual StudentAcademicStanding AcademicStanding { get; set; }
   }

   public enum StudentAcademicStanding {
      Excellent,
      Good,
      Fair,
      Poor,
      Terrible
   }
}

ご覧のとおり、列挙には、Excellent、Good、Fair、Poor、Terribleなどのさまざまな値が含まれている可能性があります。

マッピングファイルにジャンプすると、これらの各プロパティが、新しく追加された AcademicStanding プロパティを含むマッピングファイルにリストされていることがわかります。

<?xml version = "1.0" encoding = "utf-8" ?>
<hibernate-mapping xmlns = "urn:nhibernate-mapping-2.2"
   assembly = "NHibernateDemoApp" namespace = "NHibernateDemoApp">

   <class name = "Student">

      <id name = "ID">
         <generator class = "native"/>
      </id>

      <property name = "LastName"/>
      <property name = "FirstName" column = "FirstMidName" type = "String"/>
      <property name = "AcademicStanding"/>
   </class>

</hibernate-mapping>

データベースも変更する必要があるため、SQL Serverオブジェクトエクスプローラーに移動し、データベースを右クリックして[新しいクエリ]オプションを選択します。

新しいクエリ

クエリエディターを開き、次のクエリを指定します。

DROP TABLE [dbo].[Student]

CREATE TABLE [dbo].[Student] (
   [ID] INT IDENTITY (1, 1) NOT NULL,
   [LastName] NVARCHAR (MAX) NULL,
   [FirstMidName] NVARCHAR (MAX) NULL,
   [AcademicStanding] NCHAR(10) NULL,
   CONSTRAINT [PK_dbo.Student] PRIMARY KEY CLUSTERED ([ID] ASC)
);

このクエリは、最初に既存の学生テーブルを削除してから、新しいテーブルを作成します。

新しいテーブルの作成

上記のように、実行アイコンをクリックします。 クエリが正常に実行されると、メッセージが表示されます。

データベースとテーブルのドロップダウンを展開し、Studentテーブルを右クリックして、View Designerを選択します。

テーブルのドロップダウン

これで、新しく作成されたテーブルが表示されます。これには、新しいプロパティAcademicStandingもあります。

アカデミックスタンディング

次の Program.cs ファイルに示すように、2つのレコードを追加しましょう。

using HibernatingRhinos.Profiler.Appender.NHibernate;
using NHibernate.Cfg;
using NHibernate.Dialect;
using NHibernate.Driver;

using System;
using System.Linq;
using System.Reflection;

namespace NHibernateDemoApp {

   class Program {

      static void Main(string[] args) {

         NHibernateProfiler.Initialize();
         var cfg = new Configuration();

         String Data Source = asia13797\\sqlexpress;
         String Initial Catalog = NHibernateDemoDB;
         String Integrated Security = True;
         String Connect Timeout = 15;
         String Encrypt = False;
         String TrustServerCertificate = False;
         String ApplicationIntent = ReadWrite;
         String MultiSubnetFailover = False;

         cfg.DataBaseIntegration(x = > { x.ConnectionString = "Data Source +
            Initial Catalog + Integrated Security + Connect Timeout + Encrypt +
            TrustServerCertificate + ApplicationIntent + MultiSubnetFailover";

            x.Driver<SqlClientDriver>();
            x.Dialect<MsSql2008Dialect>();
         });

         cfg.AddAssembly(Assembly.GetExecutingAssembly());
         var sefact = cfg.BuildSessionFactory();

         using (var session = sefact.OpenSession()) {
            using (var tx = session.BeginTransaction()) {

               var student1 = new Student {
                  ID = 1,
                  FirstName = "Allan",
                  LastName = "Bommer",
                  AcademicStanding = StudentAcademicStanding.Excellent
               };

               var student2 = new Student {
                  ID = 2,
                  FirstName = "Jerry",
                  LastName = "Lewis",
                  AcademicStanding = StudentAcademicStanding.Good
               };

               session.Save(student1);
               session.Save(student2);
               var students = session.CreateCriteria<Student>().List<Student>();
               Console.WriteLine("\nFetch the complete list again\n");

               foreach (var student in students) {
                  Console.WriteLine("{0} \t{1} \t{2} \t{3}", student.ID,
                     student.FirstName, student.LastName, student.AcademicStanding);
               }

               tx.Commit();
            }

            Console.ReadLine();
         }
      }
   }
}

アプリケーションを実行してみましょう。コンソールウィンドウに次の出力が表示されます。

Fetch the complete list again

1 Allan Bommer Excellent
2 Jerry Lewis Good

では、Student Tableを右クリックして、データベースを見てみましょう。

データベース

[データの表示]を選択すると、次のスクリーンショットに示すように、学生テーブルに2つのレコードが表示されます。

データの表示

2つのレコードが追加され、アランにはAcademicStanding 0があり、ジェリーにはAcademicStanding 1があることがわかります。 これは、.Netでは最初の列挙値のデフォルトが0であるためです。これは、 StudentAcademicStanding を見ると優れています。 一方、Student.csファイルではGoodが2番目であるため、値は1です。