尝试在实体框架中实现UnitOfWork

发布于 2024-10-19 09:14:43 字数 7338 浏览 1 评论 0原文

我正在尝试了解工作单元模式。但是,我很难找到一个不太简单或不太复杂的示例。因此决定尝试根据我所读到的内容写一些自己的东西。我想知道我所做的事情是否可以接受。我正在尝试将各层解耦。我创建 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();
    }
}

I'm am trying to learn about the Unit Of Work pattern. However, I am having trouble finding an example that is not too simple or too complicated. So decided to try and write something of my own taking from what I have read. I was wondering if what I have done is acceptable. I am trying to have the layers decoupled. The reasons I created the DatabaseManager was to avoid sending the context to the other layers. In the end this will be the DAL for a MVC application with a middle layer (business)

Thanks for your input.

Code:

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();
        }

    }

EDIT: New Code

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();
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

南烟 2024-10-26 09:14:43

我认为您的工作单元实施很好并且应该有效。

这里还有其他可能的实现:

// 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;
    }

    ...
}

如果您将工作单元和存储库实现放置到单独的程序集中,那么应该就足够了。使用 ObjectContext 将是 EF DAL 程序集的内部实现,上层将不依赖于 EF 及其程序集。

这可以通过引入 DALFactory 来进一步改进。 Factory 将负责实例化和处置 ObjectContext 以及创建 unitOfWork 和存储库。它将消除 UoW 和存储库之间的紧密耦合。

我也在使用这个 实现将 UoW 和存储库的抽象工厂结合在一起,但自从我写了这个答案以来,我对它进行了一些修改。现在我的实现没有每个存储库的属性。相反,它使用通用方法返回所请求实体类型的存储库。存储库内部存储在字典中。但这个实现并不是很干净 UoW。

另一种流行的实现是:

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

public class UnitOfWork : ObjectContext, IUnitOfWork
{

}

I think your Unit of Work implementation is good and it should work.

Here you have other possible implementations:

// 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;
    }

    ...
}

If you place unit of work and repository implementations to separate assembly it should be enough. Working with ObjectContext will be internal implementation of EF DAL assembly and upper layers will have no dependency to EF and its assemblies.

This can bu further improved by initroducing DALFactory. Factory will be responsible for instancing and disposing ObjectContext and creating unitOfWork and repositories. It will remove tight coupling between UoW and Repository.

I'm also using this implementation which couples UoW and abstract factory for repositories but I have modified it little bit since I wrote that answer. Now my implementation doesn't have property for each repository. Instead it uses generic method which returns repository for requested entity type. Repositories are internally stored in dictionary. But this implementation is not very clean UoW.

Another popular implementation is:

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

public class UnitOfWork : ObjectContext, IUnitOfWork
{

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文