首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

EntityFramework 領域驅動設計實踐(九):倉儲深度實作——事務上下文與多 ORM 支援

     編輯:關於.NET

核心課題:同一事務上下文中協調多倉儲操作

DDD 倉儲目的:隱藏持久化技術細節,保持領域模型純粹。需解決:事務邊界、倉儲實例獲取、多持久化技術可替換。

統一事務上下文介面

interface IRepositoryTransactionContext : IDisposable {
    IRepository<TEntity> GetRepository<TEntity>() where TEntity : EntityObject, IAggregateRoot;
    void BeginTransaction();
    void Commit();
    void Rollback();
}

倉儲由 Context 產出,自動知悉所屬事務。

EntityFramework 實作:EdmRepositoryTransactionContext

internal class EdmRepositoryTransactionContext : IRepositoryTransactionContext {
    ObjectContext _objContext;
    Dictionary<Type, object> _repoCache = new Dictionary<Type, object>();

    public EdmRepositoryTransactionContext(ObjectContext ctx) { _objContext = ctx; }

    public IRepository<TEntity> GetRepository<TEntity>() where TEntity : EntityObject, IAggregateRoot {
        if (_repoCache.TryGetValue(typeof(TEntity), out var repo)) return (IRepository<TEntity>)repo;
        var newRepo = new EdmRepository<TEntity>(_objContext);
        _repoCache[typeof(TEntity)] = newRepo;
        return newRepo;
    }
    public void BeginTransaction() { /* EF 由 ObjectContext 管理,無需顯式開始 */ }
    public void Commit() => _objContext.SaveChanges();
    public void Rollback() { /* EF 自動回滾,Dispose 時處理 */ }
    public void Dispose() { _repoCache.Clear(); _objContext.Dispose(); }
}

NHibernate 實作:NHibernateRepositoryTransactionContext

internal class NHibernateRepositoryTransactionContext : IRepositoryTransactionContext {
    ITransaction _tx;
    Dictionary<Type, object> _repoCache = new Dictionary<Type, object>();
    public ISession Session => DatabaseSessionFactory.Instance.Session;

    public IRepository<TEntity> GetRepository<TEntity>() where TEntity : EntityObject, IAggregateRoot {
        if (_repoCache.TryGetValue(typeof(TEntity), out var repo)) return (IRepository<TEntity>)repo;
        var newRepo = new NHibernateRepository<TEntity>(Session);
        _repoCache[typeof(TEntity)] = newRepo;
        return newRepo;
    }
    public void BeginTransaction() => _tx = Session.BeginTransaction();
    public void Commit() => _tx.Commit();
    public void Rollback() => _tx.Rollback();
    public void Dispose() { _tx.Dispose(); if (Session.IsOpen) Session.Close(); }
}

搭配單例 DatabaseSessionFactory 管理 NHibernate Session。

領域層使用:Castle Windsor 整合

配置檔注入 ObjectContext、EdmRepository、EdmRepositoryTransactionContext。測試代碼:

using (var tx = container.Resolve<IRepositoryTransactionContext>()) {
    tx.BeginTransaction();
    try {
        var cust = Customer.CreateCustomer(...);
        tx.GetRepository<Customer>().Add(cust);
        tx.Commit();
    } catch { tx.Rollback(); throw; }
}

測試通過,資料正確持久化。

NHibernate 相容性調整:T4 模板加虛擬屬性

NHibernate 需屬性為 virtual 以支援延遲載入 Proxy。修改 EF T4 模板 WritePrimitiveTypeProperty、WriteComplexTypeProperty,在屬性宣告處加入 virtual 關鍵字,避免直接修改生成代碼。

總結

倉儲實作完全解耦技術細節,領域模型純粹度由 DI 保障。事務上下文統一協調多倉儲,支援 EF/NHibernate 熱插拔。下一步:領域事件進一步解耦。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved