【问题标题】:What's DataService Best practice using Entity Framework and Repository and UnitOfWork Patterns什么是使用实体框架和存储库以及 UnitOfWork 模式的 DataService 最佳实践
【发布时间】:2013-11-08 19:02:09
【问题描述】:

我正在使用 EF 和 MVVM 模式。我的问题是关于数据访问层的。在 DAL 我有以下课程:

  1. MyObjectContext 现在在技术上是标准的 ObjectContext,但稍后会添加一些 Unit-of-work 方法。

  2. Repository<TModel> 处理不同 ObjectSet 上最需要的查询(例如 Add、GetAll、...)。

  3. 一堆DataServices,它们利用存储库为Core 提供更高级别的数据访问。

我正在做的项目是一个业务应用程序,到目前为止大约有 100 个 EntitySet,有时用户的单次交互可能涉及多达 20 个不同的 EntitySet(更新大部分他们)。我目前将.Include(params string[]) 添加到我的查询中以防止ObjectContextDisposedException,但这似乎不是一个可靠的解决方案。

问题是我是否应该在每个 DataService 方法中创建MyObjectContext 的实例(以及因此存储库)(如以下代码,在我看来,Unit 的能力在这种情况下,工作量将毫无用处) 或者我应该在 DataService 之外创建它并通过它们的构造函数(或直接传递给每个 DataService 方法)将其传递给 DataServices 以处理一堆数据库操作(不同的表和查询)在一起。怎么做?

MyObjectContext 是这样的:

public class MyObjectContext : ObjectContext, IUnitOfWork
{
    public MyObjectContext()
        : base("name=EdmContainer", "EdmContainer")
    {
        ContextOptions.LazyLoadingEnabled = true;
    }

    #region IUnitOfWork Members
    public void Commit()
    {
        SaveChanges();
    }
    #endregion
}

这就是Repository 的样子:

public class Repository<TModel>
{
    private readonly SoheilEdmContext _context;

    public Repository(IUnitOfWork unitOfWork)
    {
        if (unitOfWork == null)
            throw new ArgumentNullException("unitOfWork");

        _context = unitOfWork as SoheilEdmContext;
    }
    public TModel FirstOrDefault(Expression<Func<TModel, bool>> where)
    {
        return _context.CreateObjectSet<TModel>().FirstOrDefault(where);
    }
    public void Add(TModel entity)
    {
        _context.CreateObjectSet<TModel>().AddObject(entity);
    }
    ...
}

这就是常见的DataService 的样子:

public class JobDataService : IDataService<Job>
{
    #region IDataService<Job> Members
    public Job GetSingle(int id)
    {
        Job model = null;
        using (var context = new MyObjectContext())
        {
            var repos = new Repository<Job>(context);
            model = repos.FirstOrDefault(x => x.Id == id);
        }
        return model;
    }

    public IEnumerable<Job> GetAll()
    {
        using (var context = new MyObjectContext())
        {
            var repos = new Repository<Job>(context);
            var models = repos.GetAll();
            return models;
        }
    }

    public IEnumerable<Job> GetActives()
    {
        throw new NotImplementedException();
    }

    public int AddModel(Job model)
    {
        using (var context = new MyObjectContext())
        {
            var repos = new Repository<Job>(context);
            repos.Add(model);
            context.SaveChanges();
        }
    }

    public void UpdateModel(Job model)
    {
        throw new NotImplementedException();
    }

    public void DeleteModel(Job model)
    {
        using (var context = new MyObjectContext())
        {
            var repos = new Repository<Job>(context);
            var model = repos.FirstOrDefault(x => x.Id == model.Id);
            if (model == null) return;
            repos.Delete(model);
            context.SaveChanges();
        }
    }
    #endregion
}

任何想法或见解都会受到赞赏。

【问题讨论】:

    标签: entity-framework repository data-access-layer unit-of-work dataservice


    【解决方案1】:

    您可以在每个服务中创建 MyObjectContext 的实例,例如 JobDataService,但是这会使您的代码变得混乱并且难以维护。在 DataService 之外创建 MyObjectContext 的实例更好。你现在所拥有的,如果你有 100 个 EntitySet,你必须创建 100 个 DataService。那是因为这里使用“Repository Pattern”和“UnitOfWork”效率不高。我建议执行以下操作:

    ObjectContext

    public class MyObjectContext : ObjectContext
    {
        public MyObjectContext() : base("name=EdmContainer", "EdmContainer")
        {
            ContextOptions.LazyLoadingEnabled = true;
        }
    
        #region IUnitOfWork Members
        public void Commit()
        {
            SaveChanges();
        }
        #endregion
    }
    

    通用存储库

     public interface IRepository<TModel> where TModel : class
        {
            void Add(TModel entity);
            IEnumerable<TModel> GetAll();
            // Do some more implement
        }
    
    
        public class Repository<TModel> : IRepository<TModel> where TModel : class
        {
            private readonly ObjectContext _context;
    
            public Repository(ObjectContext context)
            {
                _context = context;
            }
    
            public virtual void Add(TModel entity)
            {
                _context.CreateObjectSet<TModel>().AddObject(entity);
            }
    
            public virtual IEnumerable<TModel> GetAll()
            {
                return _context.CreateObjectSet<TModel>();
            }
        }
    

    工作单位

    public interface IUnitOfWork : IDisposable
    {
        IRepository<Job> Jobs { get; }
        IRepository<User> Users { get;} 
        void Commit();
    }
    
        public class UnitOfWork : IUnitOfWork
        {
            private readonly SoheilEdmContext _context;
            private readonly IRepository<Job> _jobRepository;
            private readonly IRepository<User> _userRepository; 
    
            public UnitOfWork(SoheilEdmContext context)
            {
                _context = context;
                _jobRepository = new Repository<Job>(_context);
                _userRepository = new Repository<User>(_context);
            }
            public IRepository<Job> Jobs{get { return _jobRepository; }}
            public IRepository<User> Users{get { return _userRepository; }}
            public void Commit(){_context.Commit();}
            public void Dispose()
            {
                if (_context != null)
                {
                    _context.Dispose();
                }
    
                GC.SuppressFinalize(this);
            }
    

    JodDataService

    public interface IDataService
            {
                IEnumerable<Job> GetAll();
            }
    
            public class DataService : IDataService
            {
                private readonly IUnitOfWork _unitOfWork;
                public DataService(IUnitOfWork unitOfWork)
                {
                    _unitOfWork = unitOfWork;
                }
    
                public IEnumerable<Job> GetAll()
                {
                    return _unitOfWork.Jobs.GetAll();
                }
            }
    

    这里我使用接口来实现一切,如果你想做同样的事情,你需要使用 IoC Container。我用的是“Simple Injector”,你可以在这里找到它:

    Simple Injector

    另外一个建议,如果你觉得你有太多的 I/O 操作需要实现,比如数据库访问、查询数据等,你应该考虑使用异步。下面是一个关于异步的好视频。

    How to Build ASP.NET Web Applications Using Async

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-15
      • 1970-01-01
      相关资源
      最近更新 更多