.NET管理图层关系 [英] .NET Managing Layers Relationships

查看:94
本文介绍了.NET管理图层关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

实际上,我重新我的项目的默认架构。
在这篇文章中我希望你不只是帮助我,但想想,告诉我们,提高presented方式。这可能是非常有用的挑战。
此默认架构可与所有自由共享。
因此,这里是说明:
基本的 MVC 是我们的观点。我们遵循的 OOP 并层编程概念。同时,我们会使用 SQL Server的 EF DB首先即可。
因此,这里是香港专业教育学院做了什么至今:
香港专业教育学院创建4层在我的解决方案:


  1. 域:JUST域类

  2. DAL:负责访问数据,包括UOW和存储库和数据访问相关的验证。

  3. BL:唯一负责业务逻辑和DAL的唯一老板。

  4. UI:这是不是那么重要! (因为即使它也许一个控制台应用程序!)

香港专业教育学院实施BL与通用funcs中像 GETALL getById 和污物funcs.these funcs中会叫DAL通用funcs中这也是准备好了。
现在一个重要的问题是:是不是实现DAL funcs中的GENERIC?
请考虑以下情况:

从UI,我们发布了一个模型来行动,并在行动中我们称之为BL Func键( BL.insert (型号))。在 BL.Insert FUNC会打电话像 DAL.Add (模型)(BL通知将再次调用DAL和意志告诉它就是了)。现在 DAL.Add FUNC将不得不插入3条记录为3个不同的表(模型是从UI层传递)。
我觉得这不能由DAL GENERIC funcs中来实现。那么,什么是执行层和关系注意到分离忧虑的正确和标准的方式?

在我的行动,我将有:

  [HttpPost]
公众的ActionResult插入()
{
    Bl.EntityBase.Article.Insert(新的第());
    返回RedirectToAction(「指数」);
}

在BL我会:

 公共无效插入(T OBJ)
{
    Da.Repository< T>()插入(OBJ)。
}

在我DAL我有:

 公共虚拟无效插入(T实体)
{
    DbEntityEntry dbEntityEntry = Db.Entry(实体);
    如果(dbEntityEntry.State!= EntityState.Detached)
    {
        dbEntityEntry.State = EntityState.Added;
    }
    其他
    {
        Set.Add(实体);
    }
}


解决方案

您应该与你的通用仓库实施Repository模式DAL。
为了把抽象你必须使用IRepository接口的它的实现应该使用依赖解析器注入。
您也可以通过接口实现BL(服务)是相同的。

下面是一个很好的讨论:<一href=\"http://stackoverflow.com/questions/5049363/difference-between-repository-and-service-layer\">Difference库和服务层之间?

您也可以使用组工作模式改进。

下面是一个完整的code片段,显示我们如何能够实现多层次之间的抽象:


 公共接口IRepository&LT; T&GT;其中T:类
    {
        的DbContext的getContext();
        IQueryable的&LT; T&GT;得到所有();
        IQueryable的&LT; T&GT; FindBy(前pression&LT;&Func键LT; T,BOOL&GT;&GT; predicate);
        无效添加(T实体);
        无效删除(T实体);
        无效DeleteAll(IEnumerable的&LT; T&GT;实体);
        无效编辑(T实体);
        布尔任何();
    }


 公共类资源库&LT; T&GT; :IRepository&LT; T&GT;其中T:类
{
    私人只读的DbContext _context;
    私人只读IDbSet&LT; T&GT; _dbset;    公共库(的DbContext上下文)
    {
        _context =背景;
        _dbset = context.Set&LT; T&GT;();
    }    公共虚拟的DbContext的getContext()
    {
        返回_context;
    }    公共虚拟的IQueryable&LT; T&GT;得到所有()
    {
        返回_dbset;
    }    公众的IQueryable&LT; T&GT; FindBy(前pression&LT;&Func键LT; T,BOOL&GT;&GT; predicate)
    {
        VAR的查询= _dbset.Where(predicate).AsQueryable();
        返回查询;
    }    公共虚拟无效添加(T实体)
    {
        _dbset.Add(实体);
    }    公共虚拟无效删除(T实体)
    {
        VAR进入= _context.Entry(实体);
        entry.State = EntityState.Deleted;
        _dbset.Remove(实体);
    }    公共虚拟无效DeleteAll(IEnumerable的&LT; T&GT;实体)
    {
        的foreach(在实体VAR ENT)
        {
            VAR进入= _context.Entry(ENT);
            entry.State = EntityState.Deleted;
            _dbset.Remove(ENT);
        }
    }    公共虚拟无效编辑(T实体)
    {
        VAR进入= _context.Entry(实体);
        _dbset.Attach(实体);
        entry.State = EntityState.Modified;
    }    公共虚拟BOOL任何()
    {
        返回_dbset.Any();
    }
}


UOW

  public接口IUnitOfWork:IDisposable接口
    {
        IRepository&LT; TEntity&GT; GetRepository&LT; TEntity&GT;()其中TEntity:类;
        无效保存();
    }


 公共类的UnitOfWork&LT; TContext&GT; :IUnitOfWork哪里TContext:的DbContext,新的()
    {
        私人只读的DbContext _ctx;
        私人只读字典&LT;类型,对象&gt; _repositories;
        私人布尔_disposed;        公众的UnitOfWork()
        {
            _ctx =新TContext();
            _repositories =新词典&LT;类型,对象&gt;();
            _disposed = FALSE;
        }        公共IRepository&LT; TEntity&GT; GetRepository&LT; TEntity&GT;()其中TEntity:类
        {
            //检查该词典键包含Model类
            如果(_repositories.Keys.Contains(typeof运算(TEntity)已))
            {
                //返回库为Model类
                返回_repositories [typeof运算(TEntity)已作为IRepository&LT; TEntity取代;
            }            //如果该模型类库不存在,创建它
            变种库=新库&LT; TEntity&GT;(_ CTX);            //将它添加到字典
            _repositories.Add(typeof运算(TEntity)已,库);            返回库;
        }        公共无效保存()
        {
            //保存所有修改在一起
            _ctx.SaveChanges();
        }        公共无效的Dispose()
        {
            处置(真);
            GC.Sup pressFinalize(本);
        }        受保护的虚拟无效的Dispose(BOOL处置)
        {
            如果(!_disposed)
            {
                如果(处置)
                {
                    _ctx.Dispose();
                }                _disposed = TRUE;
            }
        }
    }


服务


 公共接口IService
 {
   IList的&LT;用户&GT; GetUserDetails(INT用户id); }


 公共类服务:IService
 { 私人只读IRepository&LT;用户&GT; _userRepository; 公共服务(IUnitOfWork的UnitOfWork)
        {
           _unitOfWork =的UnitOfWork;
       _userRepository = _unitOfWork.GetRepository&LT;用户&GT;();
        }    公众的IList&LT;用户&GT; GetUserDetails(INT用户id)
    {
        返回_userRepository.GetAll();    } }


控制器


 公共类HomeController的//使用已在服务中使用相同的图案{私人只读IService _service;公众的HomeController(IService服务)
{
_Service =服务;
}
公众的ActionResult指数()
{返回_Service。 GetUserDetails(/ *用户ID * /);}

}


希望这code可以帮助许多用户,你当然。

I'm actually recreating the default architecture of my projects. In this post I want you not just help me,but think,tell and improve presented ways. This can be very useful challenge. This default architecture can be freely shared with all. So here is description: Basically MVC is our point of view. We follow OOP and layer programming concepts. Also we will use SQL Server and EF DB First. So here is what ive done till now: Ive created 4 layers in my solution:

  1. Domain: JUST domain classes
  2. DAL: responsible for accessing data, containing UOW and repositories and data access related validations.
  3. BL: unique responsible of business logic and unique boss of DAL.
  4. UI: which is not so important! (as even it maybe a console app!)

Ive implemented BL with generic funcs like getAll and getById and crud funcs.these funcs would call DAL generic funcs which is also ready. Now an important question is: is it right to implement DAL funcs as GENERIC? Please consider this scenario :

From UI we post a model to action and in action we call a BL Func (BL.insert(model)). The BL.Insert func would call something like DAL.Add(model) (notice BL will call DAL once and will tell it what it wants). now the DAL.Add func would have to insert 3 records into 3 different tables (model is passed from UI layer). I think this cant be achieved by DAL GENERIC funcs. So what is the correct and standard way of implementing Layers and relationships with noticing the Separation Of Concerns?

In my action i would have:

[HttpPost]
public ActionResult Insert()
{ 
    Bl.EntityBase.Article.Insert(new Article()); 
    return RedirectToAction("Index");
}

in BL I would have:

public void Insert(T obj)
{
    Da.Repository<T>().Insert(obj);
}

And in my DAL I have:

public virtual void Insert(T entity)
{
    DbEntityEntry dbEntityEntry = Db.Entry(entity);
    if (dbEntityEntry.State != EntityState.Detached)
    {
        dbEntityEntry.State = EntityState.Added;
    }
    else
    {
        Set.Add(entity);
    }
}

解决方案

You should implement Repository pattern with generic repositories in you DAL . In order to put abstraction you have to use IRepository interface an its implementation should be injected using dependency resolver . Also you can achieve the same in BL(Service) using interface .

Here is a good discussion : Difference between Repository and Service Layer?

You can also improve it using Unit Of Work pattern.

Here is a complete code snippet which shows how can we achieve abstraction between multiple layers :


Repository

public interface IRepository<T> where T : class
    {
        DbContext GetContext();
        IQueryable<T> GetAll();
        IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
        void Add(T entity);
        void Delete(T entity);
        void DeleteAll(IEnumerable<T> entity);
        void Edit(T entity);
        bool Any();
    }


public class Repository<T> : IRepository<T> where T : class
{
    private readonly DbContext _context;
    private readonly IDbSet<T> _dbset;

    public Repository(DbContext context)
    {
        _context = context;
        _dbset = context.Set<T>();
    }

    public virtual DbContext GetContext()
    {
        return _context;
    }

    public virtual IQueryable<T> GetAll()
    {
        return _dbset;
    }

    public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate)
    {
        var query = _dbset.Where(predicate).AsQueryable();
        return query;
    }

    public virtual void Add(T entity)
    {
        _dbset.Add(entity);
    }

    public virtual void Delete(T entity)
    {
        var entry = _context.Entry(entity);
        entry.State = EntityState.Deleted;
        _dbset.Remove(entity);
    }

    public virtual void DeleteAll(IEnumerable<T> entity)
    {
        foreach (var ent in entity)
        {
            var entry = _context.Entry(ent);
            entry.State = EntityState.Deleted;
            _dbset.Remove(ent);
        }
    }

    public virtual void Edit(T entity)
    {
        var entry = _context.Entry(entity);
        _dbset.Attach(entity);
        entry.State = EntityState.Modified;
    }

    public virtual bool Any()
    {
        return _dbset.Any();
    }
}


UOW

public interface IUnitOfWork : IDisposable
    {
        IRepository<TEntity> GetRepository<TEntity>() where TEntity : class;      
        void Save();
    }


 public class UnitOfWork<TContext> : IUnitOfWork where TContext : DbContext, new()
    {
        private readonly DbContext _ctx;
        private readonly Dictionary<Type, object> _repositories;
        private bool _disposed;

        public UnitOfWork()
        {
            _ctx = new TContext();
            _repositories = new Dictionary<Type, object>();
            _disposed = false;
        }

        public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
        {
            // Checks if the Dictionary Key contains the Model class
            if (_repositories.Keys.Contains(typeof (TEntity)))
            {
                // Return the repository for that Model class
                return _repositories[typeof (TEntity)] as IRepository<TEntity>;
            }

            // If the repository for that Model class doesn't exist, create it
            var repository = new Repository<TEntity>(_ctx);

            // Add it to the dictionary
            _repositories.Add(typeof (TEntity), repository);

            return repository;
        }

        public void Save()
        {
            // save all changes together
            _ctx.SaveChanges();
        }

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

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposed)
            {
                if (disposing)
                {
                    _ctx.Dispose();
                }

                _disposed = true;
            }
        }
    }


Service


public interface IService
 {
   IList<Users> GetUserDetails(int userId);

 }


public class Service : IService
 {

 private readonly IRepository<Users> _userRepository;

 public Service (IUnitOfWork unitOfWork)
        {
           _unitOfWork = unitOfWork;
       _userRepository=_unitOfWork.GetRepository<Users>();
        }

    public  IList<Users> GetUserDetails(int userId)
    {
        return _userRepository.GetAll();

    }

 }


Controller


 public class HomeController

// use the same patter which has been used in service 

{

private readonly IService _service;

public HomeController(IService service)
{
_service=service;
}


public ActionResult Index()
{

return _service. GetUserDetails(/*userid*/);

}

}


Hope this code will help many users and you of course.

这篇关于.NET管理图层关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆