日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用NHibernate 3.2实现Repository(ORuM)(三)NHibernate、Mapping、Mapping-By-Code

發布時間:2023/12/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用NHibernate 3.2实现Repository(ORuM)(三)NHibernate、Mapping、Mapping-By-Code 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

NHibernate使用時通常是先定義實體類,再為實體類映射數據庫關系,NHibernate映射是使用XML文件形式的。

當我們Confrontation NHibernate時Mapping的過程:
  解析讀取Mapping文件
  將Mapping文件反序列化(Deserialize)為XmlDeserialized(就是NHibernate.Cfg.MappingSchema.HbmMapping類)
  將HbmMapping類Bind為元數據映射(Mapping-MetaDate),(就是NHibernate.Cfg.Mappings類)
  Build SessionFactory

NHibernate映射文件生成方式:
  手動編寫XML方式
  工具軟件生成
  NHibernate.Mapping.Attributes

  
NHibernate3.2版本集成Mapping-By-Code(代碼映射),其設計思想來源于ConfORM,代碼整體構思基于"Loquacious"模式,而不是"fluent-interface"。在NHibernate.Mapping.ByCode命名空間下。


Mapping-By-Code(代碼映射)與其他映射方式不同,Mapping-By-Code是手動配置實體映射,編譯映射并轉換為HbmMapping對象,調用Configuration類的void AddDeserializedMapping(HbmMapping mappingDocument, string documentFileName)方法配置Configuration,其他映射(例如Fluent NHibernate、MyGeneration、Visual NHibernate等)實際上是調用AddXmlReader()方法后,反序列化為HbmMapping對象,然后再調用AddDeserializedMapping方法配置Configuration。最后BuildSessionFactory。

ModelMapper核心是配置領域模型映射,編譯并轉換為HbmMapping對象。按照其功能ModelMapper類有四個部分,分別是:
  特定映射(Specific Mapper),對特定的類或者特定的某個組件設置定制化映射。由Class、Subclass、JoinedSubclass、UnionSubclass、Component方法提供。
  Conformist映射(Conformist Mapping),是以Class-By-Class方式映射,然后加入ModelMapper類。
事件攔截器(Events Interceptor),在每種映射行為前后,都定義了事件攔截器,可以通過事件攔截器定義約束。從設計角度上看是對ModelMapper類提供了擴展性。
  編譯映射(CompileMapping),把程序中的領域實體的映射編譯并轉換為NHibernate使用的HbmMapping對象。CompileMappingFor、      CompileMappingForEach方法指定特定領域實體,CompileMappingForAllExplicitAddedEntities和CompileMappingForEachExplicitAddedEntity方法已經顯式指定提供映射的實體。

Mapping-By-Code使用方法:
1、基本映射
ModelMapper提供一種基本映射方式:使用Class方法對實體類特定映射。

var mapper = new ModelMapper();
mapper.Class<Genre>(cm =>
{
cm.Id(x => x.Id, map =>
{
map.Column("GenreId");
map.Generator(Generators.Identity);
});
cm.Property(x => x.Name);
});

2、Conformist映射
ModelMapper提供另外一種Conformist映射方式:class-by-class方式,即每個類定義一個類去映射,然后調用AddMapping方法把映射加入ModelMapper對象。

public class GenreMapping : ClassMapping<Genre>
{
public GenreMapping()
{
Id(x => x.Id, map =>
{
map.Column("GenreId");
map.Generator(Generators.Identity);
});
Property(x => x.Name);
}
}

3.約定
ModelMapper提供了很多事件監聽器,可以通過它擴展ModelMapper。其中就是自定義約定。其實上面定義的映射從設計思想上面說也是一種約定,暫時可以稱作特定約定(Specific-Convetions)。以Before開頭的事件監聽稱作前置約定(Pre-Conventions)。從人性化角度看前置約定(Pre-Conventions)比較民主(democratic),我們映射時可以使用特定約定(Specific-Convetions)。以After開頭的事件監聽稱作后置約定(Post-Conventions)或者稱作Hard-Conventions。從人性化角度看后置約定(Post-Conventions)就比較共和(republican),不管前面怎么特定,到最后一律使用后置約定(Post-Conventions)所規定的"條約"。

var mapper = new ModelMapper();
mapper.BeforeMapClass += (mi, t, cam) =>
{
cam.Id(x =>
{
x.Column(t.Name + "ID");
x.Generator(Generators.Identity);
});
cam.Table(prefix+t.Name + "s");
};


常用方法:

//ID映射
Id(x => x.Id, map =>
{
map.Column("GenreId");
map.Generator(Generators.Identity);
});

//Version映射
Version(x => x.Version, map => { });

//Property映射:
Property(x => x.Name);

//ManyToOne映射
ManyToOne(x => x.Genre);

//OneToMany映射
Bag(x => x.Albums, map => { });

//Component映射
Component(x => x.Address, cm => {
cm.Property(p => p.City);
cm.Property(p => p.Country);
cm.Property(p => p.State);
cm.Property(p => p.Street);
cm.Property(p => p.Zip);
});

編譯生成HbmMapping對象:

var mapper = new ModelMapper();
mapper.AddMappings(Assembly.GetExecutingAssembly().GetExportedTypes());
HbmMapping domainMapping = mapper.CompileMappingForAllExplicitlyAddedEntities();


使用Conformist映射結合約定的方式實現實體類與數據庫的映射

完整代碼

ClassMappings.cs using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NHibernate.Mapping.ByCode.Conformist;
using MVCQuick.Models;
using NHibernate.Mapping.ByCode;

namespace MVCQuick.Framework.Repository.NHibernate
{
public class EntityBaseMapping<TEntity> : ClassMapping<TEntity> where TEntity : EntityBase
{
public EntityBaseMapping()
{
Id(x => x.Id);

Version(x => x.Version, map => { });
}

}

public class GenreMapping : EntityBaseMapping<Genre>
{
public GenreMapping()
{
Property(x => x.Name);
Property(x => x.Description);
Bag(x => x.Albums, map => {
map.Cascade(Cascade.All);
map.Inverse(true);
});
}
}

public class ArtistMapping : EntityBaseMapping<Artist>
{
public ArtistMapping()
{
Property(x => x.Name);
Component(x => x.Address, cm => {
cm.Property(p => p.City);
cm.Property(p => p.Country);
cm.Property(p => p.State);
cm.Property(p => p.Street);
cm.Property(p => p.Zip);
});
Bag(x => x.Albums, map => { });
}
}

public class AlbumMapping : EntityBaseMapping<Album>
{
public AlbumMapping()
{
Property(x => x.Title);
Property(x => x.Price);
Property(x => x.AlbumArtUrl);
ManyToOne(x => x.Genre);
ManyToOne(x =>x.Artist);
}
}
}

在Bag映射是,直接使用ModelMapper會報錯

var mapper = new ModelMapper();
mapper.AddMappings(Assembly.GetExecutingAssembly().GetExportedTypes());
HbmMapping domainMapping = mapper.CompileMappingForAllExplicitlyAddedEntities();

報錯原因及解決方法如下(http://fabiomaulo.blogspot.com/2011/07/nhibernate-playing-with-mapping-by-code.html)
We can’t define the one-to-many relation using the ModelMapper because the responsibility to define/discover all relation is delegated to the IModelInspector injected to the ModelMapper instance (note that I wrote instance). Out-of-the-box you can find some implementations of IModelInspector but if you want continue maintaining most of things under your control and you want learn the new mapping-by-code step-by-step you can simply use a class inherited from the “”default”” ExplicitlyDeclaredModel. In this case the implementation

需要提供一個IModelInspector

EntityModelInspector.cs using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NHibernate.Mapping.ByCode;
using System.Reflection;

namespace MVCQuick.Framework.Repository.NHibernate
{
public class EntityModelInspector : ExplicitlyDeclaredModel
{
public override bool IsOneToMany(MemberInfo member)
{
if (IsBag(member))
{
return true;
}
return base.IsOneToMany(member);
}
}
}

使用方法

ModelMapper mapper = new ModelMapper(new EntityModelInspector());

?

單元測試代碼

RepositoryTests.cs using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using NHibernate.Mapping.ByCode;
using MVCQuick.Framework.Repository.NHibernate;
using MVCQuick.Models;
using MVCQuick.Framework.Repository;
using NHibernate;
using System.Diagnostics;
using System.Reflection;
using MVCQuick.Framework;
using NHibernate.Cfg.MappingSchema;

namespace MVCQuick.Tests
{

[TestFixture]
public class RepositoryTests
{
[Test]
public void SaveEntity()
{
ModelMapper mapper = new ModelMapper(new EntityModelInspector());

mapper.BeforeMapClass += (mi, t, cam) =>
{
cam.Id(x =>
{
x.Column(t.Name + "ID");
x.Generator(Generators.Identity);
});
cam.Table(t.Name + "s");
};

mapper.AddMappings(typeof(EntityBase).Assembly.GetExportedTypes());


var hbmMappings = mapper.CompileMappingForAllExplicitlyAddedEntities();


Debug.WriteLine(hbmMappings.AsString());



using (SQLiteDatabaseProvider provider = new SQLiteDatabaseProvider())
{
provider.AddMappings(hbmMappings, "Repository.Tests");
provider.BuildSchema();
ISession session = provider.OpenSession();

IRepository<int, Genre> genreRepository =
new NHibernateRepository<int, Genre>(session);
Genre genre = new Genre { Name = "Genre-aa", Description = "aaaa" };
genreRepository.Save(genre);
IList<Genre> genreList = genreRepository.FindAll();
Assert.AreEqual(genreList.Count, 1);
Assert.AreEqual(genreList[0].Name, "Genre-aa");
Assert.AreEqual(genreList[0].Description, "aaaa");


IRepository<int, Artist> artistRepository =
new NHibernateRepository<int, Artist>(session);
Artist artist = new Artist { Name = "Artist-bb" };
artistRepository.Save(artist);
IList<Artist> artistList = artistRepository.FindAll();
Assert.AreEqual(artistList.Count, 1);
Assert.AreEqual(artistList[0].Name, "Artist-bb");

Debug.WriteLine("genre Id:" + genre.Id);
Debug.WriteLine("genre HashCode:" + genre.GetHashCode());
Debug.WriteLine("artist Id:" + artist.Id);
Debug.WriteLine("artist HashCode:" + artist.GetHashCode());
Assert.AreNotEqual(genre, artist);

IRepository<int, Album> albumRepository =
new NHibernateRepository<int, Album>(session);
Album album = new Album { Title = "Album-CC", Genre = genre, Artist = artist };
albumRepository.Save(album);
album = new Album { Title = "Album-DD", Genre = genre, Artist = artist };
albumRepository.Save(album);
IList<Album> albumtList = albumRepository.FindAll();
Assert.AreEqual(albumtList.Count, 2);
Assert.AreEqual(albumtList[0].Title, "Album-CC");
Assert.AreEqual(albumtList[1].Title, "Album-DD");
Assert.AreEqual(albumtList[0].Genre.Name, "Genre-aa");
Assert.AreEqual(albumtList[1].Genre.Name, "Genre-aa");

IList<Album> albumtList2 = albumRepository.Find("Title", "Album-DD");
Assert.AreEqual(albumtList2.Count, 1);



Debug.WriteLine("genre Version:" + genre.Version);
Assert.AreEqual(genre.Albums, null);
genre.Albums = new List<Album>();
((List<Album>)genre.Albums).Add(albumtList[0]);
((List<Album>)genre.Albums).Add(albumtList[1]);
genreRepository.Save(genre);
Debug.WriteLine("genre Version:" + genre.Version);
genreList = genreRepository.FindAll();
Assert.AreEqual(genreList[0].Albums.Count<Album>(), 2);

genreList = genreRepository.FindAll();
Assert.AreEqual(genreList.Count, 1);
genreRepository.Delete(genre);
genreList = genreRepository.FindAll();
Assert.AreEqual(genreList.Count, 0);

albumtList = albumRepository.FindAll();
Assert.AreEqual(albumtList.Count, 0);


artistList = artistRepository.FindAll();
Assert.IsNull(artistList[0].Address);
artist.Address = new Address();
artist.Address.City = "Beijing";
artist.Address.Country = "China";
artistRepository.Update(artist);
artistList = artistRepository.FindAll();
Assert.AreEqual(artistList[0].Address.City, "Beijing");
Assert.AreEqual(artistList[0].Address.Country, "China");


}
}
}
}

測試結果

?


測試輸出:

***** MVCQuick.Tests.RepositoryTests.SaveEntity
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" namespace="MVCQuick.Models" assembly="MVCQuick" xmlns="urn:nhibernate-mapping-2.2">
? <class name="Genre" table="Genres">
??? <id name="Id" column="GenreID" type="Int32">
????? <generator class="identity" />
??? </id>
??? <version name="Version" />
??? <property name="Name" />
??? <property name="Description" />
??? <bag name="Albums" inverse="true" cascade="all">
????? <key column="Genre" />
????? <one-to-many class="Album" />
??? </bag>
? </class>
? <class name="Artist" table="Artists">
??? <id name="Id" column="ArtistID" type="Int32">
????? <generator class="identity" />
??? </id>
??? <version name="Version" />
??? <property name="Name" />
??? <component class="Address" name="Address">
????? <property name="City" />
????? <property name="Country" />
????? <property name="State" />
????? <property name="Street" />
????? <property name="Zip" />
??? </component>
??? <bag name="Albums">
????? <key column="Artist" />
????? <one-to-many class="Album" />
??? </bag>
? </class>
? <class name="Album" table="Albums">
??? <id name="Id" column="AlbumID" type="Int32">
????? <generator class="identity" />
??? </id>
??? <version name="Version" />
??? <property name="Title" />
??? <property name="Price" />
??? <property name="AlbumArtUrl" />
??? <many-to-one name="Genre" />
??? <many-to-one name="Artist" />
? </class>
</hibernate-mapping>

??? PRAGMA foreign_keys = OFF

??? drop table if exists Genres

??? drop table if exists Artists

??? drop table if exists Albums

??? PRAGMA foreign_keys = ON

??? create table Genres (
??????? GenreID? integer primary key autoincrement,
?????? Version INT not null,
?????? Name TEXT,
?????? Description TEXT
??? )

??? create table Artists (
??????? ArtistID? integer primary key autoincrement,
?????? Version INT not null,
?????? Name TEXT,
?????? City TEXT,
?????? Country TEXT,
?????? State TEXT,
?????? Street TEXT,
?????? Zip TEXT
??? )

??? create table Albums (
??????? AlbumID? integer primary key autoincrement,
?????? Version INT not null,
?????? Title TEXT,
?????? Price NUMERIC,
?????? AlbumArtUrl TEXT,
?????? Genre INT,
?????? Artist INT,
?????? constraint FKA0BD20AAE3A37A45 foreign key (Genre) references Genres,
?????? constraint FKA0BD20AAA67656D9 foreign key (Artist) references Artists
??? )
NHibernate: INSERT INTO Genres (Version, Name, Description) VALUES (@p0, @p1, @p2); select last_insert_rowid();@p0 = 1 [Type: Int32 (0)], @p1 = 'Genre-aa' [Type: String (0)], @p2 = 'aaaa' [Type: String (0)]
NHibernate: SELECT this_.GenreID as GenreID0_0_, this_.Version as Version0_0_, this_.Name as Name0_0_, this_.Description as Descript4_0_0_ FROM Genres this_
NHibernate: INSERT INTO Artists (Version, Name, City, Country, State, Street, Zip) VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6); select last_insert_rowid();@p0 = 1 [Type: Int32 (0)], @p1 = 'Artist-bb' [Type: String (0)], @p2 = NULL [Type: String (0)], @p3 = NULL [Type: String (0)], @p4 = NULL [Type: String (0)], @p5 = NULL [Type: String (0)], @p6 = NULL [Type: String (0)]
NHibernate: SELECT this_.ArtistID as ArtistID1_0_, this_.Version as Version1_0_, this_.Name as Name1_0_, this_.City as City1_0_, this_.Country as Country1_0_, this_.State as State1_0_, this_.Street as Street1_0_, this_.Zip as Zip1_0_ FROM Artists this_
genre Id:1
genre HashCode:430785402
artist Id:1
artist HashCode:1282642567
NHibernate: INSERT INTO Albums (Version, Title, Price, AlbumArtUrl, Genre, Artist) VALUES (@p0, @p1, @p2, @p3, @p4, @p5); select last_insert_rowid();@p0 = 1 [Type: Int32 (0)], @p1 = 'Album-CC' [Type: String (0)], @p2 = 0 [Type: Decimal (0)], @p3 = NULL [Type: String (0)], @p4 = 1 [Type: Int32 (0)], @p5 = 1 [Type: Int32 (0)]
NHibernate: INSERT INTO Albums (Version, Title, Price, AlbumArtUrl, Genre, Artist) VALUES (@p0, @p1, @p2, @p3, @p4, @p5); select last_insert_rowid();@p0 = 1 [Type: Int32 (0)], @p1 = 'Album-DD' [Type: String (0)], @p2 = 0 [Type: Decimal (0)], @p3 = NULL [Type: String (0)], @p4 = 1 [Type: Int32 (0)], @p5 = 1 [Type: Int32 (0)]
NHibernate: SELECT this_.AlbumID as AlbumID2_0_, this_.Version as Version2_0_, this_.Title as Title2_0_, this_.Price as Price2_0_, this_.AlbumArtUrl as AlbumArt5_2_0_, this_.Genre as Genre2_0_, this_.Artist as Artist2_0_ FROM Albums this_
NHibernate: SELECT this_.AlbumID as AlbumID2_0_, this_.Version as Version2_0_, this_.Title as Title2_0_, this_.Price as Price2_0_, this_.AlbumArtUrl as AlbumArt5_2_0_, this_.Genre as Genre2_0_, this_.Artist as Artist2_0_ FROM Albums this_ WHERE this_.Title like @p0;@p0 = 'Album-DD' [Type: String (0)]
genre Version:1
NHibernate: UPDATE Genres SET Version = @p0, Name = @p1, Description = @p2 WHERE GenreID = @p3 AND Version = @p4;@p0 = 2 [Type: Int32 (0)], @p1 = 'Genre-aa' [Type: String (0)], @p2 = 'aaaa' [Type: String (0)], @p3 = 1 [Type: Int32 (0)], @p4 = 1 [Type: Int32 (0)]
genre Version:2
NHibernate: SELECT this_.GenreID as GenreID0_0_, this_.Version as Version0_0_, this_.Name as Name0_0_, this_.Description as Descript4_0_0_ FROM Genres this_
NHibernate: SELECT this_.GenreID as GenreID0_0_, this_.Version as Version0_0_, this_.Name as Name0_0_, this_.Description as Descript4_0_0_ FROM Genres this_
NHibernate: DELETE FROM Albums WHERE AlbumID = @p0 AND Version = @p1;@p0 = 1 [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)]
NHibernate: DELETE FROM Albums WHERE AlbumID = @p0 AND Version = @p1;@p0 = 2 [Type: Int32 (0)], @p1 = 1 [Type: Int32 (0)]
NHibernate: DELETE FROM Genres WHERE GenreID = @p0 AND Version = @p1;@p0 = 1 [Type: Int32 (0)], @p1 = 2 [Type: Int32 (0)]
NHibernate: SELECT this_.GenreID as GenreID0_0_, this_.Version as Version0_0_, this_.Name as Name0_0_, this_.Description as Descript4_0_0_ FROM Genres this_
NHibernate: SELECT this_.AlbumID as AlbumID2_0_, this_.Version as Version2_0_, this_.Title as Title2_0_, this_.Price as Price2_0_, this_.AlbumArtUrl as AlbumArt5_2_0_, this_.Genre as Genre2_0_, this_.Artist as Artist2_0_ FROM Albums this_
NHibernate: SELECT this_.ArtistID as ArtistID1_0_, this_.Version as Version1_0_, this_.Name as Name1_0_, this_.City as City1_0_, this_.Country as Country1_0_, this_.State as State1_0_, this_.Street as Street1_0_, this_.Zip as Zip1_0_ FROM Artists this_
NHibernate: UPDATE Artists SET Version = @p0, Name = @p1, City = @p2, Country = @p3, State = @p4, Street = @p5, Zip = @p6 WHERE ArtistID = @p7 AND Version = @p8;@p0 = 2 [Type: Int32 (0)], @p1 = 'Artist-bb' [Type: String (0)], @p2 = 'Beijing' [Type: String (0)], @p3 = 'China' [Type: String (0)], @p4 = NULL [Type: String (0)], @p5 = NULL [Type: String (0)], @p6 = NULL [Type: String (0)], @p7 = 1 [Type: Int32 (0)], @p8 = 1 [Type: Int32 (0)]
NHibernate: SELECT this_.ArtistID as ArtistID1_0_, this_.Version as Version1_0_, this_.Name as Name1_0_, this_.City as City1_0_, this_.Country as Country1_0_, this_.State as State1_0_, this_.Street as Street1_0_, this_.Zip as Zip1_0_ FROM Artists this_


文中部分內容轉載自YJingLee's Blog(http://www.cnblogs.com/lyj/)

轉載于:https://www.cnblogs.com/guyoung/archive/2011/10/06/2200000.html

總結

以上是生活随笔為你收集整理的使用NHibernate 3.2实现Repository(ORuM)(三)NHibernate、Mapping、Mapping-By-Code的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。