この記事では、私が定期的にアクセスするすべての情報をまとめて、インターネットまたはコードで探し回ることにしました。 これらは、NHibernateのマッピングとリンクです。 メモ記事のようなものになります。 過度に書き過ぎないように決めました(たとえば、NHibernate Queriesについてはほとんど書きませんでした)。したがって、各見出しには、メモ記事の作成時に依存した記事(英語)へのリンクがあります。 彼女があなたの役に立つことを願っています。
ASP.NET MVC 4とSQL Server 2008の例を示します(ところで、後者にアクセスすることはほとんどありません。データの保存方法を確認するだけですが、接続文字列に言及しています)。 具体的かつ簡潔に記述しようとします。理解できない瞬間がある場合は
、ASP.NET MVCとSQL Serverを使用したFluentNHibernateのレッスンの記事をお願いし
ます。 すべてがより詳細に説明されている
パート1 。 それでは、始めましょう、Visual Studioを起動して:
- 新規プロジェクトFile-> New-> Projectを作成します。
- ASP.NET MVC 4(.Net Framework 4)を選択し、 NHibernateMVCと呼びます。
- Modelsフォルダーで、NHibernateフォルダーを作成します。
- パッケージマネージャーコンソールで、 インストールパッケージnhibernateを記述します (以下の例はFluentNhibernateでも動作します(検証済み!):インストールパッケージFluentnhibernate)。
Nhibernateをインストールした後、アプリケーションのクラスをデータベースのテーブルに関連付ける(マップする)方法に関して疑問が生じます。 NHibernateには、次のような3種類のマッピングがあります。
- XML * .hbm.xmlマッピングファイルを作成する
- 属性 これは、XMLマッピングのアドインです。 マッピングは.NET属性のように見えます
- コードによるマッピング。 -xml-files *の代わりに.cs ConfORMマッピングクラスが使用されます
- 流Flu Create * .cs Fluentマッピングクラス
マッピングオプション。1.XMLファイル開発されたマッピングの最初。
長所:
+インターネットには多くの例があります。
+他のすべてのメソッド(属性およびFluent)は、これらのxmlファイルを受信するように削減されます。
短所:
-インテリセンスが完全に欠落しています(!)。
-コンパイル時の検証はありません。
それでは、それを見てみましょう。
NHibernateをインストールした後、Nhibernate.cfg.xmlファイルをModels-> NHibernateフォルダーに追加します
<?xml version="1.0" encoding="utf-8" ?> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> <session-factory> <property name="connection.provider"> NHibernate.Connection.DriverConnectionProvider </property> <property name="connection.driver_class"> NHibernate.Driver.SqlClientDriver </property> <property name="connection.connection_string"> Server=...\SQLENTERPRISE; database=NhibernateTutor; Integrated Security=SSPI; </property> <property name="dialect"> NHibernate.Dialect.MsSql2008Dialect </property> </session-factory> </hibernate-configuration>
私はSQL Serverを使用しているため、SqlClientDriverを選択しました。 別のデータベースを使用している場合は、NHibernate.Driverのリストはここで
NHibernate.Driverにあります。私はSQL Server 2008を持っているので、MsSql2008Dialectを選択しました。すべての方言はここで表示できます
SQL方言SQL ServerでNhibernateTutorデータベースを作成し、接続文字列を記述します。 この記事では、テーブルを作成せず、NHibernate自体がテーブルを生成します。
次に、Books.csクラスをModelsフォルダーに追加します。
public class Book { public virtual int Id { get; set; } public virtual string Name { get; set; } public virtual string Description { get; set; } }
(PSすべてのフィールドは仮想でなければなりません-この要件は、遅延読み込み(遅延読み込み)およびNHibnerateがオブジェクトのすべての変更を追跡するために必要です。)
クラスを作成したら、そのマッピングを作成します。 これを行うには、Models-> NHibernateフォルダーにxml-file“ Book.hbm.xml”を作成します。 (
注意!。- すべてのマッピングファイルには、* .hbm.xml拡張子が必要です。
- このファイルのプロパティに移動し(Book.hbm.xml-> [プロパティ]を右クリック)、[詳細]リストで[ ビルドアクション]プロパティを[ 埋め込みリソース]に変更します 。 他の* .hbm.xmlファイルについても同じことを再度行う必要があります。 指定しない場合は、行configuration.AddAssembly(typeof(Book).Assembly)で指定します。 クラスNhibernateHelper(後で作成されます)は、クラスBookがそのマッピングファイルを見つけることができないというエラーが発生します。
<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" assembly="NhibernateMVC" namespace="NhibernateMVC.Models"> <class name="Book" dynamic-update="true" > <cache usage="read-write"/> <id name="Id" type="int"> <generator class="native" /> </id> <property name="Name" /> <property name="Description" /> </class> </hibernate-mapping>
ここで何に注意する必要がありますか。 まず、アセンブリと名前空間はBookクラスと同じでなければなりません。 idが<generator class = "native" />だったのは、guidが好きではなく、データベースの機能(これはSql ServerのID)に応じて、使用するタイプ(identity、sequenceまたはhilo)を決定するためです。
xmlマッピングを作成したら、ルートディレクトリにNHibernateHelper.csクラスを作成します。
public class NHibernateHelper { public static ISession OpenSession() { var configuration = new Configuration(); var configurePath = HttpContext.Current.Server.MapPath(@"~\Models\Nhibernate\nhibernate.cfg.xml"); configuration.Configure(configurePath);
ISessionConfigurationのセットアップの
詳細については、ISessionFactoryの構成を参照してください。これらすべての操作の最後に、次のファイルが作成されました。
ここで、NHibernateがデータベースにBookテーブルを作成する方法を見てみましょう。 ControllersフォルダーにHomeControllerクラスを作成し、次のコードを記述します。
public ActionResult Index() { var session = NHibernateHelper.OpenSession(); return View(); }
ビューがどのように表示されるか今は興味がありません。空にします。 アプリケーションを起動し、SQL Serverデータベースに移動します(できれば!)NhibernateTutorデータベースにBookテーブルが表示されます。 そこで、必要に応じてデータ型を変更できます(nvarchar(255)do nvarchar(MAX)、but not int!)。 データを入力するまで、最初に接続を設定します(1対1接続が表示されると、MindテーブルがBookテーブルに対応していないというエラーが表示されます)またはデータを入力してから削除します。
次に、テーブル間のリレーションシップの設定に移りましょう。
1.1関係多対多Book.cs | Author.cs |
---|
private ISet<Author> _authors; public virtual ISet<Author> Authors { get { return _authors ?? (_authors = new HashSet<Author>()); } set { _author = value; } }
| private ISet<Book> _books; public virtual ISet<Book> Books{ get { return _books?? (_books= new HashSet<Book>()); } set { _books= value; } }
|
Book.hbm.xml | Author.hbm.xml |
---|
<property ~~~/> ........................................... <set name="Authors" table="Book_Author" cascade="save-update"> <key column="BookId"/> <many-to-many class="Author" column="AuthorId"/> </set>
| <property ~~~/> ........................................... <set name="Books" table="Book_Author" inverse="true" cascade = "save-update"> <key column="AuthorId"/> <many-to-many class="Book" column="BookId"/> </set>
|
これらのクラスのxml-mappingを見てみましょう。 setタグから始めましょう。これは.NET ISetに使用されます。 コレクションのタグの詳細については、
コレクションの値のコレクションをご覧ください。
コレクションの表と、それらに適用されるタグを以下に示します。
.Netコレクション | マッピング |
---|
IEnumerable / ICollection / IList | かばん |
順序付きのIList | リスト |
イセット | セット |
IDictionary | 地図 |
- table = "Book_Author"は、多対多の関係に必要なBook_Authorステージングテーブルを作成する属性です。
- name = "Books / Authors"-コレクションの名前を示します
- cascade = "save-update"-保存および更新時に、それに関連付けられたテーブルも保存および更新されることを示します。 ビューカスケード= "all | none | save-update | delete | all-delete-orphan"、詳細はこちらLifeCyclesおよびオブジェクトグラフ
- inverse =“ true”は、反対側のBookテーブルが親であり(関係を担当する)、更新されることを意味します。 詳細はここで見つけることができます
- key column =“ BookId”-BookテーブルがBookIdキーによってBook_Authorテーブルに関連付けられることを示します
- 多対多のクラス=「著者」列=「AuthorId」-Bookテーブルがキー「AuthorId」によってAuthorテーブルに関連付けられることを示します
多対一(1対多)Book.cs | Series.cs |
---|
public virtual Series Series { get; set; }
| private IList<Book> _books; public virtual IList<Book> Books { get { return _books ?? (_books = new List<Book>()); } set { _books = value; } }
|
Book.hbm.xml
| Series.hbm.xml
|
---|
<many-to-one name="Series" class="Series" column="Series_id" cascade = "save-update"/>
| <bag name="Books" inverse="true"> <key column="Series_id"/> <one-to-many class="Book"/> </bag>
|
だから、私は何と言うことができますか? IListがあり、column = "Series_id"がBookテーブルにSeries_Id列を作成するため、タグ "bag"を使用しました。残りは上記で説明しました。
一対一Book.cs | Mind.cs |
---|
private Mind _mind; public virtual Mind Mind { get { return _mind ?? (_mind = new Mind()); } set { _mind = value; } } | public virtual Book Book { get; set; } |
Book.hbm.xml | Mind.hbm.xml |
---|
<one-to-one name="Mind" class="Mind" constrained="true" cascade = "All"/> | <one-to-one name="Book" class="Book" /> |
そして、ここはすでに面白いです! constrained =“ true”は、Bookテーブルの各レコードについてMindテーブルにレコードが存在する必要があることを意味します。つまり、BookテーブルのIdはMindテーブルのIdと等しくなければなりません。 Mindテーブルを忘れてBookオブジェクトを保存しようとすると、Nhibernateはデータを保存できないという例外をスローします。 つまり、最初にBookオブジェクトのMindオブジェクトを作成する必要があります。 常にMindオブジェクトを作成するのは非常に面倒なので、保存するときにBookオブジェクトを作成すると、以下のコードでMindオブジェクトが初期化され、Mindテーブルに入力する時間が常にあります。
private Mind _mind; public virtual Mind Mind { get { return _mind ?? (_mind = new Mind()); } set { _mind = value; } }
Cascade =“ All”テーブルを保存、変更、削除すると、Bookテーブルも保存、変更され、Mindテーブルが削除されます。 したがって、すべての接続を作成しました。データを保存、編集、または削除して接続を確認します。 以下のネタバレの下の詳細。
マッピングパフォーマンステスト:CRUD操作次のようにHomeControllerを変更して、データベースにデータを保存、更新、削除するテストアプリケーションを作成しましょう(コードの不要なセクションについてコメントします)。
public ActionResult Index() { using (ISession session = NHibernateHelper.OpenSession()) { using (ITransaction transaction = session.BeginTransaction()) {
次のように表現を変更します。
@model IEnumerable<NhibernateMVC.Models.Book> @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <style> th, td { border: 1px solid; } </style> </head> <body> <p>@Html.ActionLink("Create New", "Create")</p> <table> <tr> <th>@Html.DisplayNameFor(model => model.Name)</th> <th>@Html.DisplayNameFor(model => model.Mind)</th> <th>@Html.DisplayNameFor(model => model.Series)</th> <th>@Html.DisplayNameFor(model => model.Authors)</th> <th></th> </tr> @foreach (var item in Model) { <tr> <td>@Html.DisplayFor(modelItem => item.Name)</td> <td>@Html.DisplayFor(modelItem => item.Mind.MyMind)</td> @{string strSeries = item.Series != null ? item.Series.Name : null;} <td>@Html.DisplayFor(modelItem => strSeries)</td> <td> @foreach (var author in item.Authors) { string strAuthor = author != null ? author.Name : null; @Html.DisplayFor(modelItem => strAuthor) <br /> } </td> <td> @Html.ActionLink("Edit", "Edit", new { id = item.Id }) | @Html.ActionLink("Details", "Details", new { id = item.Id }) | @Html.ActionLink("Delete", "Delete", new { id = item.Id }) </td> </tr> } </table> </body> </html>
Author、Mind、およびSeriesに適切なフィールドを作成することで、自分でできると思います。 すべての操作を順番に確認すると、次のことがわかります。
- 作成および更新操作中に、Bookテーブルに関連付けられたすべてのデータが更新されます(Cascade = "save-update"またはcascade = "all"を削除すると、関連付けられたデータは保存されません)
- テーブルBook、Mind、Book_Authorからデータを削除すると、Cascade = "save-update"があるため、残りのデータは削除されません。
- テーブルBook、Mind、Book_Authorからデータを削除すると、Cascade = "save-update"があるため、残りのデータは削除されません。
さらに、
Criteriaは属性とFluentの両方で機能するため、このコードを使用して他のマッピングオプションのリンクを確認できます。 また、データベース内のキーを確認することを忘れないでください。あなたが犯した間違いは決してわかりません。これについては後で学びます。 たとえば、Bookテーブルは、BookIdキーではなく、Book_AuthorテーブルのAuthorIdをキーで参照します。
詳細情報はこちらをご覧ください。NHibernateリファレンスドキュメント2.属性Nhibernateのアドインです。
長所:
+個別のファイル(* .hbm.xml)を作成し、クラスフィールドのすぐ上に属性を書き込む必要はありません。つまり、エンティティとマッピングが近くにあります。
+ Intellisense 50/50サポート(!)。 属性(名前など)を記述するためのヒントがありますが、文字列として表示されるプロパティについてはありません。
+ xmlファイルから属性に簡単に切り替えられます。
短所:
-コードの可読性が悪化しています。
-コンパイル時の検証の欠如。
-複数の属性で構成されるプロパティの場合、インデックスを登録する必要があります。
インターネット上のNHibernate.Mapping.Attributesには、
nhibernate.infoの Webサイトにも資料がほとんどありませんが、その章は1つだけです! Nhibernate * .hbm.xmlファイルと同じ設定があります。 したがって、
厄介な * .hbm.xmlファイルの代わりに属性を使用します。 したがって、属性を使用していて問題がある場合は、* .hbm.xml-filesに適用可能なソリューションを使用してください。これらの構文は同じであるため、簡単に把握できます。
- 属性を使用する前に、最初にすべてのマッピング(* .hbm.xml)ファイルを削除します。これらは不要になります。 ( Nhibernate.cfg.xml leave!)
- 属性を操作するには、NHibernate.Mapping.Attribute.dllが必要です。 パッケージマネージャーコンソールからインストールします 。ここでInstall-Package NHibernate.Mapping.Attributesを記述します 。
- NHibernateHelperクラスを次のように変更します
public class NHibernateHelper { public static ISession OpenSession() { var configuration = new Configuration(); var configurePath = HttpContext.Current.Server.MapPath(@"~\Models\Nhibernate\nhibernate.cfg.xml"); configuration.Configure(configurePath);
- configurePath-Nhibernateファイルを構成するパスを指定します
- HbmSerializer.Default.Validate-生成されたxmlストリームの検証を有効または無効にします
- HbmSerializer.Default.Serialize-クラスをXMLファイルにシリアル化します
今こそ属性を書くときです。 次のように属性を追加してBookクラスを変更します
[Class] public class Book { [Id(0, Name = "Id")] [Generator(1, Class = "native")] public virtual int Id { get; set; } [Property] public virtual string Name { get; set; } [Property] public virtual string Description { get; set; } }
何に注意する必要がありますか? まず、マップする各プロパティに属性が必要です。 第二に、インデックスID(0 ...)およびジェネレーター(1 ...)に注意しましたか? インデックスは、複数の属性で構成されるプロパティに適用する必要があります。 これは、NHMAが属性からその場で* .hbm.xmlファイルを生成し、xml要素を書き出す順序を知る必要があるためです。 (残念ながら、リフレクションを使用した属性の順序はサポートされていません)。
Bookテーブルをデータベースから削除します(削除することはできません。これは確認のためです)。プロジェクトを実行し、データベースにBookテーブルがなかった場合は作成されます。
構文は* .hbm.xmlファイルの構文と同じであるため、関係については記述しません。唯一の違いは、コレクションの場合、インデックスを登録する必要があることです。
2.1関係(表内)多対多Book.cs | Author.cs |
---|
[Set(0, Table = "Book_Author", Cascade = "save-update")] [Key(1, Column = "BookId")] [ManyToMany(2, ClassType = typeof(Author), Column = "AuthorId")] private ISet<Author> _authors; public virtual ISet<Author> Authors { get { return _authors ?? (_authors = new HashSet<Author>()); } set { _author = value; } }
| [Set(0, Table = "Book_Author", Inverse = true, Cascade = "save-update")] [Key(1, Column = "AuthorId")] [ManyToMany(2, ClassType = typeof(Book), Column = "BookId")] private ISet<Book> _books; public virtual ISet<Book> Books{ get { return _books?? (_books= new HashSet<Book>()); } set { _books= value; } }
|
多対1、1対多Book.cs | Series.cs |
---|
[ManyToOne(Name = "Series", Column = "SeriesId", ClassType = typeof(Series), Cascade = "save-update")] public virtual Series Series { get; set; }
| [Bag(0, Name = "Books", Inverse = true)] [Key(1, Column = "SeriesId")] [OneToMany(2, ClassType = typeof(Book))] private IList<Book> _books; public virtual IList<Book> Books{ get { return _books?? (_books= new List<Book>()); } set { _books= value; } }
|
一対一Book.cs | Mind.cs |
---|
[OneToOne(Name = "Mind", ClassType = typeof(Mind), Constrained = true, Cascade = "All")] private Mind _mind; public virtual Mind Mind { get { return _mind ?? (_mind = new Mind()); } set { _mind = value; } }
| [OneToOne(Name = "Book", ClassType = typeof(Book))] public virtual Book Book { get; set; }
|
3. ByCodeのマッピング長所:
+追加のライブラリは必要ありません(属性の場合のように)
+ Intellisense 100のサポート(!)。
+ * .Hbm.xmlファイルとNhibernate.cfg.xmlは必要ありません
+ Fluent-Nhibernate(ラムダ式)を最大限に活用し、* .hbm.xmlファイルの構文を作成しました。
短所:
-カスケードのSave-Updateプロパティを削除しました(Cascade.Persistを使用できますが、それでも可能です)。
-構造(特に、クラス間の関係)は、* .hbm.xmlファイルの要素に正確に対応していません。
更新されます...- nhibernate.cfg.xmlファイルを削除します
- NHibernateHelperクラスを次のように変更します
public class NHibernateHelper { public static ISession OpenSession() { var cfg = new Configuration() .DataBaseIntegration(db => { db.ConnectionString = @"Server=..\SQLENTERPRISE;initial catalog=NhibernateTutor;Integrated Security=SSPI;"; db.Dialect<MsSql2008Dialect>(); }); var mapper = new ModelMapper(); mapper.AddMappings(Assembly.GetExecutingAssembly().GetExportedTypes()); HbmMapping mapping = mapper.CompileMappingForAllExplicitlyAddedEntities(); cfg.AddMapping(mapping); new SchemaUpdate(cfg).Execute(true, true); ISessionFactory sessionFactory = cfg.BuildSessionFactory(); return sessionFactory.OpenSession(); } }
トレンドに気づきましたか? 各メソッドは、Nhibernateのファイルの1つを削除します。 xmlファイルには* .hbm.xmlファイルとnhibernate.cfg.xmlファイルがあり、属性は不要になりました* .hbm.xmlファイルは、マッピングbyCodeでnhibernate.cfg.xmlは不要になりました。 新しいメソッドで削除されるのは興味深いことです(そしてまったく削除されますか?)。
Bookクラスとそのマッピングは次のようになります。
public class Book { public virtual int Id { get; set; } public virtual string Name { get; set; } public virtual string Description { get; set; } } public class BookMap : ClassMapping<Book> { public BookMap() { Id(x => x.Id, map => map.Generator(Generators.Native)); Property(x=>x.Name); Property(x=>x.Description); }
3.1関係(テーブル内)多対多Book.cs | Author.cs |
---|
private ISet<Author> _authors; public virtual ISet<Author> Authors { get { return _authors ?? (_authors = new HashSet<Author>()); } set { _author = value; } }
| private ISet<Book> _books; public virtual ISet<Book> Books{ get { return _books?? (_books= new HashSet<Book>()); } set { _books= value; } }
|
BookMap.cs | AuthorMap.cs |
---|
Set(a => a.Authors, c => { c.Cascade(Cascade.Persist); c.Key(k => k.Column("BookId")); c.Table("Book_Author");}, r=>r.ManyToMany(m=>m.Column("AuthorId")));
| Set(a => a.Books, c => { c.Cascade(Cascade.All); c.Key(k => k.Column("AuthorId")); c.Table("Book_Author"); c.Inverse(true); }, r => r.ManyToMany(m => m.Column("BookId")));
|
多対1、1対多Book.cs | Series.cs |
---|
public virtual Series Series { get; set; }
| private IList<Book> _books; public virtual IList<Book> Books{ get { return _books?? (_books= new List<Book>()); } set { _books= value; } }
|
BookMap.cs | SeriesMap.cs |
---|
ManyToOne(x => x.Series, c => { c.Cascade(Cascade.Persist); c.Column("Series_Id"); });
| Bag(x => x.Books, c => { c.Key(k => k.Column("Series_Id")); c.Inverse(true); }, r => r.OneToMany());
|
一対一Book.cs | Mind.cs |
---|
private Mind _mind; public virtual Mind Mind { get { return _mind ?? (_mind = new Mind()); } set { _mind = value; } }
| public virtual Book Book { get; set; }
|
BookMap.cs | Mindmap.cs |
---|
OneToOne(x=>x.Mind, c=>{c.Cascade(Cascade.All); c.Constrained(true);});
| OneToOne(x=>x.Book, c=>c.Cascade(Cascade.None));
|
詳細はこちら
StackOverflow Mapping-By-Code4.フルーエントNHibernate XMLファイルの標準表示に代わるものを提供します。 XMLファイルを記述する代わりに、厳密に型指定されたC#コードでマッピングを記述します(ラムダ式を使用)。 これにより、リファクタリングが行われ、コードが読みやすくなり、記述しやすくなります。
長所:
+ 100%インテリセンスのサポート!
+
優れたFluent-Nhibernateのドキュメント+コンパイル時の検証
+ Nhibernate.cfg.xmlファイルを作成する必要はありません。接続文字列を含むすべての設定をNhibernateHelperで指定できます。
短所:
-他のバージョンのNHibernateと比較して、マッピング構文は少し変わっています。
FluentNhibernateとNhibernateはわずかに異なるため、アプリケーションを再作成しているかのように記述させてください。 それでは、新しいアプリケーションを作成しましょう。
- パッケージマネージャーコンソールで、 install-package fluentnhibernateを記述します。
- 「Models」フォルダーで、「Book.cs」クラスを作成します(Models-> Book.cs)
- NHibernateフォルダーをモデルに追加し、NHibernateHelper.csクラスを作成します(モデル-> NHibernate-> NHibernateHelper.cs)
public class NHibernateHelper { public static ISession OpenSession() { ISessionFactory sessionFactory = Fluently.Configure() .Database(MsSqlConfiguration.MsSql2008.ConnectionString(@"Server=..\SQLENTERPRISE; initial catalog= Biblioteca; Integrated Security=SSPI;").ShowSql() ) .Mappings(m =>m.FluentMappings.AddFromAssemblyOf<Book>()) .ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(false, true)) .BuildSessionFactory(); return sessionFactory.OpenSession(); } }
このNhibernateHelper.csでは、ここでデータベースに接続文字列を書き込むことに注意してください。 はい、ラムダ式があります。
Book.csクラスを埋める
public class Book { public virtual int Id { get; set; } public virtual string Name { get; set; } public virtual string Description { get; set; } }
マッピングクラスを作成します
public class BookMap : ClassMap<Book> { public BookMap() { Id(x => x.Id); Map(x => x.Name); Map(x => x.Description); } }
次に、ControllersフォルダーにHomeControllerクラスを作成し、次のコードを記述します。
public ActionResult Index() { var session = NHibernateHelper.OpenSession(); return View(); }
ビューを作成します。SQLServerでアプリケーションを起動すると、Bookテーブルが作成されます。
4.1リレーション(テーブル内)多対多Book.cs | Author.cs |
---|
private ISet<Author> _authors; public virtual ISet<Author> Authors { get { return _authors ?? (_authors = new HashSet<Author>()); } set { _author = value; } }
| private ISet<Book> _books; public virtual ISet<Book> Books{ get { return _books?? (_books= new HashSet<Book>()); } set { _books= value; } }
|
BookMap.cs | AuthorMap.cs |
---|
HasManyToMany(x => x.Authors) .Cascade.SaveUpdate() .Table("Book_Author");
| HasManyToMany(x => x.Books) .Cascade.All() .Inverse().Table("Book_Author");
|
多対1、1対多Book.cs | Series.cs |
---|
public virtual Series Series { get; set; }
| private IList<Book> _books; public virtual IList<Book> Books{ get { return _books?? (_books= new List<Book>()); } set { _books= value; } }
|
BookMap.cs | SeriesMap.cs |
---|
References(x => x.Series).Cascade.SaveUpdate();
| HasMany(x => x.Books) .Inverse();
|
Referencesメソッドは多対1側に適用され、HasManyメソッドは他の1対多側に適用されます。
一対一Book.cs | Mind.cs |
---|
private Mind _mind; public virtual Mind Mind { get { return _mind ?? (_mind = new Mind()); } set { _mind = value; } }
| public virtual Book Book { get; set; }
|
BookMap.cs | Mindmap.cs |
---|
HasOne(x => x.Mind).Cascade.All().Constrained();
| HasOne(x => x.Book);
|
.Constrained()メソッドは、NHibernateにBookテーブルのエントリについて、Mindテーブルのエントリが一致する必要があることを伝えます(MindテーブルのIDはBookテーブルのIDと等しくなければなりません)
クエリオプション(NHibernateクエリ)NHibernateには、次のような強力なクエリツールがあります。
- メソッドsession.Getおよびsession.Load。 主キーによるオブジェクトの取得(リスト)。
- SQL(CreateSQLQueryメソッド)-主にSQLスクリプトを特定のクラスに変換するために使用されます
- HQLはSQLに似た言語で、静的クエリに適しています。
- LINQ to NHibernate-NHibernate 2xでは、linqクエリはISession.Linq <T>インターフェイスで指定されていましたが、これは単純なクエリでうまく機能しました。 Nhibernate 3のリリース(インターフェイスがISession.Query <T>に変更された)により、プログラマーの間では広く使用されていませんでしたが、より多くの機能が追加されました。
- 基準(よく使用されます)-動的なクエリの構築に適しています。プロパティは文字列として設定されます。
- QueryOver(よく使用されます)-NHibernate 3バージョンで最初に登場し、動的クエリの構築にも適しています。インテリセンスがサポートされています
IDリクエスト
SQLCreateQueryメソッド
制限付きリスト
Join、Projectingなど、NHibernate Queryで同様のクエリを作成したかったのですが、
NHibernate Queriesおよび
NHibernate More Queriesからそれに関する優れた記事がすでにあることが
わかりました。QueryOverに興味がある場合、そのクエリのタイプは
NH3のQueryOverにあります。
この記事は終わりに近づいているので、次の資料で仕上げたいと思いました。
遅延ロードと熱心なロード(遅延ダウンロードと貪欲なダウンロード)遅延読み込みとイーガー読み込みは、NHibernateが必要なデータをエンティティのナビゲーションプロパティに読み込むために使用する方法です。
->
遅延読み込み-遅延読み込み 。 エンティティ(ブック)に初めてアクセスすると、対応する関連データは読み込まれません。 ただし、ナビゲーションプロパティ(Book.Genres)に初めてアクセスすると、関連付けられたデータが自動的に読み込まれます。 同時に、データベースに対して多くのクエリが作成されます。1つはエンティティ用で、もう1つはデータがダウンロードされるたびに実行されます。
// (View) @foreach (var item in Model) { // Book @foreach (var genre in item.Genres) { // Genres, Book @Html.DisplayFor(modelItem => genre.Name) <br /> } }
->
Eagerloading-貪欲なダウンロード 。 エンティティにアクセスすると、データがロードされます。 通常、この後にすべてのデータを返す結合要求が続きます。
// (View) @foreach (var item in Model) { // Book . @foreach (var genre in item.Genres) { @Html.DisplayFor(modelItem => genre.Name) <br /> } }
NHibernateは、貪欲なダウンロードにフェッチ戦略を使用します。例としてQuery Overを使用して、EagerLoadingおよびLazyLoadingのダウンロードを見てみましょう。---クエリオーバー-ダウンロードコードの遅延読み込み--- using (ISession session = NHibernateHelper.OpenSession()) { Genre genreAl = null; Author authorAl = null; Series seriesAl = null; var books = session.QueryOver<Book>() //Left Join Genres .JoinAlias(p => p.Authors, () => authorAl, JoinType.LeftOuterJoin) .JoinAlias(p => p.Series, () => seriesAl, JoinType.LeftOuterJoin)
---クエリオーバー-EagerLoadingダウンロードコード--- using (ISession session = NHibernateHelper.OpenSession()) { var books = session.QueryOver<Book>() .Fetch(a => a.Authors).Eager.Fetch(s => s.Series).Eager .TransformUsing(Transformers.DistinctRootEntity).List(); return View(books);
ご覧のとおり、FetchはすべてのデータをBookオブジェクトにすぐにバインドするため、前の例のようにLeftJoinを使用しませんでした。Fecthについて-ここで読むことができる戦略Nhibernate Fetch戦略と、レイジーまたはイーガーロードを使用したマッピングについて-here 属性lazy、fetch、batch-size。NhibernateInfo に関する記事もあります-遅延熱心な読み込みこの記事は終わりました。ご清聴ありがとうございました。