DDD與NCommon&NHibernate之一

  • 1964
  • 0

摘要: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);
        }}