0

Unit Of Work パターンについて学習しようとしています。ただし、単純すぎず複雑すぎない例を見つけるのに苦労しています。それで、私が読んだことから私自身の何かを書いてみることにしました. 自分のしたことが受け入れられるかどうか疑問に思っていました。レイヤーを分離しようとしています。DatabaseManager を作成した理由は、コンテキストを他のレイヤーに送信しないようにするためでした。最終的に、これは中間層 (ビジネス) を持つ MVC アプリケーションの DAL になります。

ご意見ありがとうございます。

コード:

public interface IDatabaseFactory : IDisposable
    {
        ObjectContext Get();
    }

    public class DatabaseFactory : Disposable, IDatabaseFactory
    {
        private ObjectContext _dataContext;

        #region IDatabaseFactory Members

        public ObjectContext Get()
        {
            return _dataContext ?? (_dataContext = (new MyMemberDatabase()));
        }

        #endregion

        protected override void DisposeCore()
        {
            if (_dataContext != null)
                _dataContext.Dispose();
        }
    }

    public static class DatabaseManager
    {
        private static readonly Dictionary<Guid, ObjectContext> ContextLists = new Dictionary<Guid, ObjectContext>();

        public static ObjectContext GetContext(Guid id)
        {
            if (!ContextLists.ContainsKey(id))
            {
                Guid newContextID = id;
                ContextLists.Add(newContextID, new DatabaseFactory().Get());
            }

            return ContextLists[id];
        }

        public static void RemoveContext(Guid id)
        {
            if (ContextLists[id] != null)

                ContextLists.Remove(id);
        }
    }

    public class Disposable : IDisposable
    {
        private bool _isDisposed;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        ~Disposable()
        {
            Dispose(false);
        }

        private void Dispose(bool disposing)
        {
            if (!_isDisposed && disposing)
            {
                DisposeCore();
            }

            _isDisposed = true;
        }

        protected virtual void DisposeCore()
        {
        }
    }

    public interface IUnitOfWork : IDisposable
    {
        Guid ContextID { get; }
        void Commit();
    }

    public class UnitOfWork : IUnitOfWork
    {
        private readonly Guid _contextID;

        public UnitOfWork()
        {
            _contextID = new Guid();
            _contextID = Guid.NewGuid();
        }

        #region IUnitOfWork Members

        public Guid ContextID
        {
            get { return _contextID; }
        }

        public void Commit()
        {
            DatabaseManager.GetContext(_contextID).SaveChanges();
        }

        public void Dispose()
        {
            DatabaseManager.RemoveContext(_contextID);
        }

        #endregion
    }


    public abstract class RepositoryBase<T> where T : class
    {
        private readonly IUnitOfWork _unitOfWork;
        private ObjectContext _context;
        private IObjectSet<T> _objectSet;

        private ObjectContext Context
        {
            get { return _context ?? (_context = DatabaseManager.GetContext(_unitOfWork.ContextID)); }
        }

        protected IObjectSet<T> ObjectSet
        {
            get { return _objectSet ?? (_objectSet = Context.CreateObjectSet<T>()); }
        }

        protected RepositoryBase(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

    }
class MemberRepository : RepositoryBase<Member>
    {
        public MemberRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
        {
        }


        public virtual void Add(Member entity)
        {
            ObjectSet.AddObject(entity);
        }

        public virtual void Delete(Member entity)
        {
            ObjectSet.DeleteObject(entity);
        }

        public virtual IEnumerable<Member> GetAll()
        {
            return ObjectSet.AsEnumerable();
        }

    }

編集: 新しいコード

public  interface IMemberRepository : IRepository
{
    void Add(Member entity);
    void Delete(Member entity);
    IEnumerable<Member> GetAll();
}
public interface IRepository
{
    IUnitOfWork UnitOfWork { get; }
}
public interface IUnitOfWork : IDisposable
{
    void Commit();
}

public class DatabaseFactory : Disposable, IDisposable
{
    private ObjectContext _dataContext;

    public ObjectContext Get()
    {
        return _dataContext ?? (_dataContext = (new MyMemberDatabase()));
    }

    protected override void DisposeCore()
    {
        if (_dataContext != null)
            _dataContext.Dispose();
    }
}
public static class DatabaseManager
{
    private static readonly Dictionary<Guid, ObjectContext> ContextLists = new Dictionary<Guid, ObjectContext>();

    public static ObjectContext GetContext(Guid id)
    {
        if (!ContextLists.ContainsKey(id))
        {
            Guid newContextID = id;
            ContextLists.Add(newContextID, new DatabaseFactory().Get());
        }
        return ContextLists[id];
    }

    public static void RemoveContext(Guid id)
    {
        if (ContextLists[id] != null)
            ContextLists.Remove(id);
    }
}
public class Disposable : IDisposable
{
    private bool _isDisposed;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~Disposable()
    {
        Dispose(false);
    }

    private void Dispose(bool disposing)
    {
        if (!_isDisposed && disposing)
        {
            DisposeCore();
        }

        _isDisposed = true;
    }

    protected virtual void DisposeCore()
    {
    }
}
public class UnitOfWork : IUnitOfWork
{
    private readonly Guid _contextID;

    public UnitOfWork()
    {
        _contextID = new Guid();
        _contextID = Guid.NewGuid();
    }

    #region IUnitOfWork Members

    internal Guid ContextID
    {
        get { return _contextID; }
    }

    public void Commit()
    {
        DatabaseManager.GetContext(_contextID).SaveChanges();
    }

    public void Dispose()
    {
        DatabaseManager.RemoveContext(_contextID);
    }

    #endregion
}
public abstract class RepositoryBase<T> : IRepository where T : class
{
    private readonly UnitOfWork _unitOfWork;
    private ObjectContext _context;
    private IObjectSet<T> _objectSet;

    public IUnitOfWork UnitOfWork
    {
        get { return _unitOfWork; }
    }

    private ObjectContext Context
    {
        get { return _context ?? (_context = DatabaseManager.GetContext(_unitOfWork.ContextID)); }
    }

    protected IObjectSet<T> ObjectSet
    {
        get { return _objectSet ?? (_objectSet = Context.CreateObjectSet<T>()); }
    }

    protected RepositoryBase(IUnitOfWork unitOfWork)
    {
        _unitOfWork = (UnitOfWork)unitOfWork;
    }

    protected RepositoryBase()
    {
        _unitOfWork = new UnitOfWork();
    }
}
public class MemberRepository :  RepositoryBase<Member> ,IMemberRepository
{
    public MemberRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
    {
    }

    public MemberRepository():base()
    {
    }

    public virtual void Add(Member entity)
    {
        ObjectSet.AddObject(entity);
    }

    public virtual void Delete(Member entity)
    {
        ObjectSet.DeleteObject(entity);
    }

    public virtual IEnumerable<Member> GetAll()
    {
        return ObjectSet.AsEnumerable();
    }
}
4

1 に答える 1

2

Unit of Work の実装は適切であり、機能するはずです。

ここには、他の可能な実装があります。

// Interface used by upper layer
public interface IUnitOfWork : IDisposable
{
    void Commit();
}

// EF dependent unit of work
public class EFUnitOfWork : IUnitOfWork
{
    private readonly ObjectContext _context = new ObjectContext(...);

    internal ObjectContext Context
    {
        get { return _context; }
    }

    ...
}

// EF dependent repository - upper layer uses interface
public abstract class EFRepositoryBase<T> : IRepository<T> where T : class
{
    private readonly ObjectContext _context;
    private IObjectSet<T> _objectSet;

    // yes unit of work and repository is tightly coupled because they both have
    // to work with EF
    public EFRepositoryBase(EFUnitOfWork unitOfWork)
    {
        _context = unitOfWork.Context;
    }

    ...
}

作業単位とリポジトリの実装を別のアセンブリに配置すれば、それで十分です。操作は EF DALObjectContextアセンブリの内部実装であり、上位層は EF とそのアセンブリに依存しません。

これは、DALFactory を導入することでさらに改善できます。Factory はObjectContextunitOfWork とリポジトリのインスタンス化と破棄と作成を担当します。これにより、UoW とリポジトリの間の密結合が解消されます。

また、UoW とリポジトリの抽象ファクトリを結合するこの実装を使用していますが、その回答を書いてから少し変更しました。現在、私の実装には各リポジトリのプロパティがありません。代わりに、要求されたエンティティ タイプのリポジトリを返すジェネリック メソッドを使用します。リポジトリは辞書に内部的に保存されます。しかし、この実装はあまりクリーンな UoW ではありません。

別の一般的な実装は次のとおりです。

// Interface used by upper layer
public interface IUnitOfWork : IDisposable
{
    void SaveChanges();
}

public class UnitOfWork : ObjectContext, IUnitOfWork
{

}
于 2011-02-28T13:20:36.687 に答える