asp.net-mvc – 需要帮助来应用SOLID原则
Juile Lerman关于“企业中的EF”的多元化课程给我留下了深刻的印象,并决定构建我的演示应用程序.
我正在使用VS 2012和最新版本的EF,SQL Server和MVC.我正在构建一个应用SOLID原则的演示应用程序.我这样做是为了更好地理解如何实现DI&单元测试. 我在这个演示应用程序中使用了DB first方法.它只包含一个名为UserDetails的表,下面是它在SQL Server中的外观.我将使用此表进行CRUD操作. 以下是我如何分层我的应用程序: 1. WESModel解决方案:该层包含我的Model1.edmx文件和上下文类,如下所示. namespace WESModel { using System; using System.Data.Entity; using System.Data.Entity.Infrastructure; using WESDomain; public partial class WESMVCEntities : DbContext { public WESMVCEntities() : base("name=WESMVCEntities") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { throw new UnintentionalCodeFirstException(); } public DbSet<UserDetail> UserDetails { get; set; } } } 2. WESDomain解决方案:该层包含我的Domain类(或POCO类).这些POCO类实际上是在我的WESModel层中自动生成的.我把它们移到了这一层.以下是单个POCO类的外观. namespace WESDomain { using System; using System.Collections.Generic; public partial class UserDetail:IUserDetail { public int Id { get; set; } public string UserName { get; set; } } } 3:WESDataLayer解决方案:该层包含对上述2层dll的引用. namespace WESDataLayer { public class UserDetailRepository : IUserDetailRepository { WESMVCEntities context = new WESMVCEntities(); public IQueryable<IUserDetail> All { get { return context.UserDetails; } } public IQueryable<IUserDetail> AllIncluding(params Expression<Func<IUserDetail,object>>[] includeProperties) { IQueryable<IUserDetail> query = context.UserDetails; foreach (var includeProperty in includeProperties) { query = query.Include(includeProperty); } return query; } public IUserDetail Find(int id) { return context.UserDetails.Find(id); } public void InsertOrUpdate(UserDetail userdetail) { if (userdetail.Id == default(int)) { // New entity context.UserDetails.Add(userdetail); } else { // Existing entity context.Entry(userdetail).State = EntityState.Modified; } } public void Delete(int id) { var userdetail = context.UserDetails.Find(id); context.UserDetails.Remove(userdetail); } public void Save() { context.SaveChanges(); } public void Dispose() { context.Dispose(); } } public interface IUserDetailRepository : IDisposable { IQueryable<IUserDetail> All { get; } IQueryable<IUserDetail> AllIncluding(params Expression<Func<UserDetail,object>>[] includeProperties); UserDetail Find(int id); void InsertOrUpdate(UserDetail userdetail); void Delete(int id); void Save(); } } 4:ConsoleApplication1解决方案:这是我的UI层.它将是我最终应用程序中的MVC应用程序.在这里,我只是查询数据库并显示数据.这就是代码的外观. namespace ConsoleApplication1 { class Program { static void Main(string[] args) { IUserDetailRepository repo = new UserDetailRepository(); var count = repo.All.ToList().Count().ToString(); Console.WriteLine("Count: {0}",count); Console.ReadLine(); } } } 问题:我的UI层没有任何引用EF DLL.但是,它有一个Repository类的实例.在MVC应用程序中,我的控制器将具有存储库类或UnitOfWork的实例. a)这是正确的做法吗? b)有什么办法可以抽象出来吗? c)如果将来我想用Dapper或任何其他ORM工具换掉EF怎么办? d)我如何在我的项目中使用我的DI工具?它应该在哪一层? e)单元测试.我知道StructureMap,并希望在这个项目中使用它,以便将来我应该能够与Ninject交换它.我如何实现这一目标? 感谢您阅读这个大问题,如果有人能指出我正确的方向,我真的很感激. 解决方法
是的,UI图层类不能对EF有任何引用.但要做到这一点,他们不能引用具体的存储库.在MVC应用程序中,如果您不使用服务层,Controller将只在IUserDetailRepository上有一个引用,并等待构造中的具体类型.
正确的做法是称为“松耦合”,似乎你的设计就是选择这种方式.
是的,您可以使用依赖性解析程序.这样,无需引用具体类型,您将只有基于抽象的代码
您必须具有数据访问层,例如,包含IXxxRepository契约的具体实现的库.在您的情况下,它将是EF实现.当您为Dapper进行更改时,您将不得不重新实现此图层.重构有一个可接受的限制.
放置DI工具的最佳位置是UI层.在应用程序启动时,您将配置依赖项绑定,一切都将自动运行;)
你想拔下你的Dependency Resolver插上另一个吗?没问题,只需在编码DR的配置时进行预测,以便与您的应用程序保持最小耦合.在某些情况下,有一些限制耦合的技巧……在我目前正在开发的项目中,我们首先有一个MVC应用程序和一个服务层,业务层,数据访问层和基础设施层.我们使用Ninject作为DR,并且基础结构和Web UI层是唯一具有Ninject参考的层.拔掉它很容易,我们已经用这种方式尝试过Unity. 还有一件事,你不应该有UserDetail的合同.没有必要,在无状态类上使用依赖注入,而不是在DTO之类的所有类上使用依赖注入. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – Visual Studio 2008,2010或2012(v11)是否写入使
- asp.net-mvc-4 – 无法从程序集’itextsharp,Version = 5.5
- asp.net – Internet Explorer中的图像加载超时
- Asp.Net Core简介与安装教程
- ASP.NET -- WebForm -- HttpRequest类的方法和属性
- asp.net – 抽象通用ODataController类导致“没有找到HTTP资
- asp.net – 如何访问listview中的按钮?特别是使用button_c
- ASP.NET拒绝访问该路径
- asp.net – 如何将会话超时设置超过20分钟.
- asp.net 关于gridview使用的一些小技巧