http://www.cnblogs.com/imythu/archive/2012/06/09/mvc-ef-design.html
http://www.cnblogs.com/imythu/archive/2012/06/09/mvc-ef-design2.html
http://www.cnblogs.com/imythu/archive/2012/06/11/mvc-ef-design3.html
介于这段时间的学习,MVC 和 Entity Framework 再加上自己对框架这部分的理解,弄了这么个Demo,希望大家能给点意见,一起讨论讨论。本章中没有多么高深的理论知识,只是个人对于架构的理解,加上MVC 和 EntityFramework,可以说是个整体的部分
先贴下我的项目的分布图:
整个项目主要采用三层架构,面向接口的编程方式。
界面层:User Interface
CinDou.Web主要放我们的Web页面,
CinDou.Route主要放置MVC中Controller,
这里我采用把Controller分离出来。个人考虑的原因是:项目比较清晰,职责比较单一。
逻辑层:Business Logic Layer
CinDou.BFactory 是逻辑工厂层,用于创建逻辑层的接口,便于界面层调用。
CinDou.IBLL 逻辑接口层
CinDou.BLL 逻辑业务层 主要负责逻辑层中的业务。
CinDou.Model 逻辑业务类
数据库层:Data Accss Layer
CinDou.DFacoty:数据工厂层,用于创建数据库层的接口,从而让逻辑层调用
CinDou.IDAL : 数据库接口层
CinDou.DAL : 数据库持久层
CinDou.EFramework: Entity Framework层
工具层:ToolKit
CinDou.Tools 常用的工具类方法层
Component :控件层
大概的一个分层是这个样子的。其实园子里有很多同学都说过这个话题,每个人对分层有各自的看法,不过看了很多文章,总感觉有点语曰不详,或者可能是我没有找到,所以个人自己写个,希望有兴趣的同学们一起讨论下。
貌似MVC现在比较热闹,所以,在这个项目中我也采取了MVC,但是MVC的Controller总是包含在站点文件夹中,这个总让我很不爽,至于为什么不爽,个人总感觉Controller是个页面的逻辑部分,一般在以前我们总放在aspx.cs文件中,但是mvc没有这个aspx.cs文件,所以,索性我们把这部分单独出来建立了CinDou.Route这个项目
为了使这个Controller能单独出来,我们必须还要做一些其它的工作:
Step1:在CinDou.Tools中建立
IRegisterRoutes.cs
using System.Web.Routing; namespace CinDou.Tools { interface IRegisterRoutes { void RegisterRoutes(RouteCollection
Routes); } } |
CinDouRoutes.cs
using System.Web.Routing; using System.Web.Mvc; namespace CinDou.Tools { class CinDouRoutes
: IRegisterRoutes { public void RegisterRoutes(RouteCollection
routes) { routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" ); routes.MapRoute( "Default" ,
//
Route name "{controller}/{action}/{id}" ,
//
URL with parameters new {
controller = "Home" ,
action = "Index" ,
id = UrlParameter.Optional } //
Parameter defaults ); } } } |
CinDouApplication.cs
using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace CinDou.Tools { public class CinDouApplication
: HttpApplication { protected void Application_Start() { CinDouRoutes
pdr = new CinDouRoutes(); AreaRegistration.RegisterAllAreas(); pdr.RegisterRoutes(RouteTable.Routes); } } } |
我们在CinDou.Tools中建立好这三个文件后,然后在CinDou.Web中引用这个Dll即可。 同时,我们修改Global.asax文件使其指向我们刚刚建立的CinDouApplication文件。右键点击Global.asax文件,点"查看标记”然后修改为:
<%@ Application Inherits="CinDou.Tools.CinDouApplication" Language="C#" %>
我们在CinDou.Route中创建创建的ProductController就能起作用了~
发了前面两篇文章后,有的同学说:“分层应该依项目而定,没有什么最好的分层,只有最合适的。” 也有同学说 “分层太复杂,才多大的项目”
在这里我想发表下我的看法,个人之言,权当讨论的话题:首先说分层应该依项目而定,这话总体来说没有错误,但是到底什么样的项目该用什么样的分层
这个没有定数,至少我还不知道这个确切的分界线~况且,我们现在可能做个小项目,到以后也许慢慢发展起来怎么办?
对于这个分层是否过于复杂,个人并不是这么看的,至少这么分层,每个分层都有其中不可少的因素在里面。前期搭建好以后,也许项目真的发展起来后,
会有助于项目真正的开发。当然,如果是小项目,个人也觉得没有必要分太多层。
好了,现在说说,我们这个EF的底层框架怎么搭建。
首先 我们现在数据库建一个表 Product 表结构如下:
在CinDou.EFramework层中建立 CinDouDbContext.cs 文件,代码如下
using
System.Data.Entity; using
System.Data.Entity.Infrastructure; using
System.Data.Entity.ModelConfiguration.Conventions; using
CinDou.Tools; using
CinDou.Model; namespace
CinDou.EFramework { string
connection= "xxxxx" ;
//数据库链接 public
class CinDouDbContext : DbContext { public
AppedDbContext() :
base(connection) {
} public
DbSet<Product> Products{get; set;} protected
override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();//移除复数表名的契约 modelBuilder.Conventions.Remove<IncludeMetadataConvention>();//防止黑幕交易
要不然每次都要访问 EdmMetadata这个表 } } } |
在 CinDou.Model 项目中建立 Product.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel.DataAnnotations; namespace CinDou.Model { public class Product { public int ID
{ get ;
set ;
} [Column( "Name" )] public string ProductName
{ get ;
set ;
} [Column( "Price" )] public decimal ProductPrice
{ get ;
set ;
} public DateTime
CreateDate { get ;
set ;
} } } |
在BFactoy和DFactory层中分别建立BLLFactory。cs 和 DALFactory.cs
using System; using System.Collections.Generic; using System.Reflection; using System.Linq; using System.Text; using CinDou.Tools; using CinDou.IBLL; using CinDou.BLL; namespace CinDou.BFactory { public sealed class BLLFactory { static string bllLayer
= WebSite.BLLAssembly; public static CinDou.IBLL.IProduct
CreateProduct() { return (CinDou.IBLL.IProduct)Assembly.Load(bllLayer).CreateInstance(bllLayer
+ ".Product" ); } } } |
using System.Reflection; using CinDou.Tools;
using CinDou.IDAL; using CinDou.DAL; namespace CinDou.DFactory { public sealed class DALFactory { static string dalLayer
= WebSite.DALAssembly; public static CinDou.IDAL.IProduct
CreateProduct() { return (CinDou.IDAL.IProduct)Assembly.Load(dalLayer).CreateInstance(dalLayer
+ ".Product" ); } } } |
这里,我们使用了反射和工厂模式。这样便于解耦和层的封闭
在CinDou.IBLL和CinDou.IDAL中分别建立IProduct.cs文件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using CinDou.Model; namespace CinDou.IBLL { public interface IProduct { bool Add(CinDou.Model.Product
product); IEnumerable<CinDou.Model.Product>
List(); } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using CinDou.Model; namespace CinDou.IDAL { public interface IProduct { bool Add(Product
product); IEnumerable<Product>
List(); } } |
然后再在CinDou.BLL和CinDou.DAL中建立Product.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using CinDou.IBLL; using CinDou.DFactory; using CinDou.IDAL; using CinDou.DAL; using CinDou.Model; namespace CinDou.BLL { public class Product
: CinDou.IBLL.IProduct { public bool Add(CinDou.Model.Product
product) { return CinDou.DFactory.DALFactory.CreateProduct().Add(product); } public IEnumerable<CinDou.Model.Product>
List() { return CinDou.DFactory.DALFactory.CreateProduct().List(); } } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Entity; using CinDou.IDAL; using CinDou.EFramework; using CinDou.Model; using CinDou.Tools; namespace CinDou.DAL { public class Product
: CinDou.IDAL.IProduct { private CinDouDbContext
CinDouDB = new CinDouDbContext; public bool Add(CinDou.Model.Product
product) { bool flag
= false ; try { CinDouDB.Products.Add(product); CinDouDB.SaveChanges(); flag
= true ; } catch {
} return flag; } public IEnumerable<CinDou.Model.Product>
List() { return CinDouDBProducts.ToList(); } } } |
我们再在CinDou.Route项目中建立 Controllers文件夹,然后建立ProductController.cs文件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.Mvc; using CinDou.IBLL; using CinDou.BFactory; namespace CinDou.Route.Controllers { public class ProductController
: Controller { public ViewResult
Index() { return View(CinDou.BFactory.BLLFactory.CreateProduct().List()); } public ActionResult
Create() { return View( new CinDou.Model.Product()); } // //
POST: /Department/Create [HttpPost] public ActionResult
Create(CinDou.Model.Product product) { bool flag
= CinDou.BFactory.BLLFactory.CreateProduct().Add(product); return RedirectToAction( "Index" ); } } } |
在CinDou.Web项目中的Views文件夹下建立Product文件夹,在里面建立Index.cshtml文件
在建立的时候,借助vs的智能感应,能非常方便的建立index.cshtml文件中的内容。
@model
IEnumerable< CinDou.Model.Product > < p > @Html.ActionLink("Create
New", "Create") </ p > < table > < tr > < th > ProductName </ th > < th > ProductPrice </ th > < th > CreateDate </ th > < th ></ th > </ tr > @foreach
(var item in Model) { < tr > < td > @Html.DisplayFor(modelItem
=> item.ProductName) </ td > < td > @Html.DisplayFor(modelItem
=> item.ProductPrice) </ td > < td > @Html.DisplayFor(modelItem
=> item.CreateDate) </ td > < td > @Html.ActionLink("Edit",
"Edit", new { id=item.ID }) | @Html.ActionLink("Details",
"Details", new { id=item.ID }) | @Html.ActionLink("Delete",
"Delete", new { id=item.ID }) </ td > </ tr > } </ table > |
项目至此,已经差不多建立完整了。最后再附上我的源码。便于理解吧~