摘要:DDD與NCommon&NHibernate之一
承前一篇,我做出以下的Feature Set
Feature Set:Storage CategoryRepository
Features:
Add Category To Repository
Get Category From Repository
Remove Category From Repository
但到實作時,會發現如果Category刪掉了,Product與Item都要被刪除,而OrderDeatil就會失去關聯。這時多半會引入軟刪除的方法,所以feature的文字需要修改。
Set Delete For Category
註:子Product與孫Item都一併設為Delete
DDD:
Domain Driven Design是目前相當主流設計方法。它說世界的物品可分成兩大類物件,Entity是可標識且獨一無二的,Value Object是無標識性,例如時間、顏色等。為了徹底分離物件間的交互作用,會把幾個物件包成一個Aggregate,只有Aggregate Root可以公開出方法。而物件則是從Repository中取出,一次取出就是一個Aggregate。由於各個Aggregate的方法只能處理各自的內容,所以還需要Service做為跨Aggregate處理程式的所在。
NCommon:
這是我蠻喜歡的DDD框架,.Net世界還有SharpArch。NCommon封裝了NHibernate、EntityFramework、LinqToSql做為底層。這種做法有好有壞,好處是寫法一致,壞處是失去了各類ORM的專屬功能。
環境:
首先設定 NCommon的使用環境。
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
var configuration = Fluently.Configure()
.Database(SQLiteConfiguration.Standard
.UsingFile("MyPetshop.db")
.ShowSql())
.Mappings(mappings => mappings.FluentMappings.AddFromAssemblyOf- ())
.ExposeConfiguration(x => x.SetProperty("connection.release_mode", "on_close"))
.BuildConfiguration();
ISessionFactory sessionFactory = configuration.BuildSessionFactory();
new SchemaExport(configuration).Execute(true, true, false);
WindsorContainer container = new WindsorContainer();
WindsorServiceLocator serviceLocator = new WindsorServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => serviceLocator);
var adapter = new WindsorContainerAdapter(container);
NCommon.Configure.Using(adapter)
.ConfigureState
()
.ConfigureData(config => config.WithSessionFactory(() => sessionFactory))
.ConfigureUnitOfWork(config => config.AutoCompleteScope()); }
Mapping:
使用Fluent Nhibernate來設定
public class CategoryMap : ClassMap
{
public CategoryMap()
{
Table("Category");
Id(x => x.CateoryId).Column("CategoryId")
.GeneratedBy.Identity();
Map(x => x.Name);
Map(x => x.IsDelete).Default("false");
HasMany(x => x.Products).Cascade.All();
}}
測試:
[TestFixture]
public class Storage_CategoryRepository : TestBase
{
[Test]
public void Add_Catorory_To_Repository()
{
using(UnitOfWorkScope scope = new UnitOfWorkScope())
{
Category category = new Category();
category.Name = "Dogs";
var repository = ServiceLocator.Current.GetInstance>();
repository.Add(category);
Assert.Greater(category.CateoryId,0);
}}