标签:
这个项目的结构,大家来拍拍砖,同时还要请多多提些问题。
项目不是为了做新闻,由于对新闻比较了解,不同的项目中也用的多,我就想通过这个项目吧新闻功能做的深入完善些,这里也就用新闻做演示用。
这个结构是根据之前的项目结构,以及院子里不是朋友们的提供的方案、代码等,整合起来的。不敢妄称为啥框架,只是希望对开发的项目能起到一些帮助作用。
第一次写blog,可能有点乱,大家见谅了。
使用结构资源
NHibernate.net
FluentNHibernate
Autofac
MVC
Jquery
项目结构
总体结构
说明下为啥这样做: 我工作的单位都是变化比较快的公司(命苦呀),很多事情都是比较杂,之前的项目就是模块太多了,维护起来很麻烦,我就想可不可以按照功能模块来划分, 吧一个模块深入,又不影响其他人的工作。。。 所以倒腾了这样的一个结果。(受到SpaceBuilder影响).
另外一个想法是:今后项目扩展性会好些; 模块的延续行也会提升。像之前在不同的公司,项目中的新闻还要拿出来改啊啥的。 如果这个结果吧新闻模块完善后,其他项目只需要引用改模块即可。
文章咨询模块
稍微了解过NHibernate.net应该能开出来大概的结构意思吧? 还是上几段代码吧。
using System; using System.Linq; using System.Text; using Job.FluenCore.Common; using Iesi.Collections.Generic; namespace Job.FluenCore.Article.Model { public class News : IEntity { /// <summary> /// 文章编号 /// </summary> public virtual int Id { get; set; } /// <summary> /// 新闻类型何种类型 /// 文章、单页 /// News.TypeId =NewsClass.TypeId /// </summary> public virtual NewsClassType TypeId { get; set; } /// <summary> /// News.ClassId =NewsClass.ClassId /// </summary> public virtual int ClassId { get; set; } /// <summary> /// 访问次数 /// </summary> public virtual int Visits { get; set; } /// <summary> /// 添加时间 /// </summary> public virtual DateTime AddTime { get; set; } /// <summary> /// 编辑时间 /// </summary> public virtual DateTime EditTime { get; set; } /// <summary> /// 文章状态 /// </summary> public virtual NewAuditType ContentStatus { get; set; } /// <summary> /// 主题 详细页 /// </summary> public virtual string Title { get; set; } /// <summary> /// 主题颜色 /// </summary> public virtual string TitleColor { get; set; } /// <summary> /// 复标题 用于首页等。 /// </summary> public virtual string TitleSub { get; set; } /// <summary> /// 内容 /// </summary> public virtual string Content { get; set; } /// <summary> /// 作者 /// </summary> public virtual string Author { get; set; } /// <summary> /// 简介 /// </summary> public virtual string Introduction { get; set; } /// <summary> /// seo /// </summary> public virtual string PageTitle { get; set; } /// <summary> /// seo /// </summary> public virtual string PageKeywords { get; set; } /// <summary> /// seo /// </summary> public virtual string PageDescription { get; set; } /// <summary> /// 置顶 /// </summary> public virtual byte IsTop { get; set; } /// <summary> /// 推荐 /// </summary> public virtual byte IsRecommend { get; set; } /// <summary> /// 回复 /// </summary> public virtual byte IsNoComment { get; set; } /// <summary> /// 文章星级 默认 0 /// </summary> public virtual short Star { get; set; } /// <summary> /// 文章排序 默认 0 /// </summary> public virtual int ContentOrder { get; set; } /// <summary> /// 文章Url /// </summary> public virtual string ContentUrl { get; set; } /// <summary> /// 缩略图 编号 /// </summary> public virtual int IndexImage { get; set; } /* /// <summary> /// 文章分类 /// 数据库字段=ClassID /// </summary> public virtual NewsClass Class { get; set; } /// <summary> /// 文章评论 /// </summary> public virtual ISet<NewsComments> Comments { get; set; } ///// <summary> ///// 图片 下载文件 ///// </summary> public virtual ISet<NewsFile> Files { get; set; } */ } }
using System; //using System.Collections.Generic; using System.Linq; using Iesi.Collections.Generic; using FluentNHibernate.Mapping; using Job.FluenCore.Article.Model; namespace Job.FluenCore.Article.Mapping { public class NewsMap : ClassMap<News> { public NewsMap() { Table("[t_News]"); Id(p => p.Id).GeneratedBy.Identity(); Map(p => p.ClassId).Not.Nullable().Default("0"); Map(p => p.Title).Not.Nullable().Length(255); Map(p => p.TitleColor).Nullable().Length(10); Map(p => p.TitleSub).Nullable().Length(255); Map(p => p.Content).Nullable().CustomSqlType("text"); Map(p => p.Author).Nullable().Length(50); Map(p => p.Introduction).Nullable().Length(1000); Map(p => p.PageTitle).Nullable().Length(100); Map(p => p.PageKeywords).Nullable().Length(100); Map(p => p.PageDescription).Nullable().Length(255); Map(p => p.IsTop).Not.Nullable().Default("0"); Map(p => p.IsRecommend).Not.Nullable().Default("0"); Map(p => p.IsNoComment).Not.Nullable().Default("0"); Map(p => p.Star).Not.Nullable().Default("0"); Map(p => p.ContentOrder).Not.Nullable().Default("0"); Map(p => p.ContentUrl).Nullable().Length(255); Map(p => p.IndexImage).Not.Nullable().Default("0"); Map(p => p.Visits).Not.Nullable().Default("0"); Map(p => p.AddTime).Not.Nullable().Default("getdate()"); Map(p => p.EditTime).Not.Nullable().Default("getdate()"); Map(p => p.ContentStatus).CustomType<NewAuditType>(); /* References<NewsClass>(p => p.Class) .LazyLoad() .Column("ClassID") .Cascade.All(); HasMany<NewsComments>(p => p.Comments) .AsSet().LazyLoad() .Inverse() // Inverse="false"(默认):父实体负责维护关联关系 Inverse="true":子实体负责维护关联关系 .KeyColumn("NewsID") .Cascade.All(); HasMany<NewsFile>(p => p.Files) .AsSet().LazyLoad() .Inverse() // Inverse="false"(默认):父实体负责维护关联关系 Inverse="true":子实体负责维护关联关系 .KeyColumn("NewsID") .Cascade.All(); */ } } }
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using Webdiyer.WebControls.Mvc; using Job.FluenCore.Common; using Job.FluenCore.DateFactory; using Job.FluenCore.Article.Mapping; using Job.FluenCore.Article.Model; namespace Job.FluenCore.Article.Repository { #region Interface public interface INewsRepository : IRepositoryBase<News> { void UpdateHitClick(int Id); } #endregion public class NewsRepository : RepositoryBase<News>, INewsRepository { public NewsRepository(IDatabaseFactory databaseFactory) : base(databaseFactory) { } public void UpdateHitClick(int Id) { var s = "update [t_News] set Visits=Visits+1 whre Id=:f1"; base.CreateSQLQuery(s) .SetInt32("f1", Id) .ExecuteUpdate(); //base.Commit(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; //using System.Data.Entity.Validation; using Webdiyer.WebControls.Mvc; using Job.FluenCore.Common; using Job.FluenCore.DateFactory; using Job.FluenCore.Article.Model; using Job.FluenCore.Article.Repository; namespace Job.FluenCore.Article.Service { public interface INewsService : IServiceBase<INewsRepository> { void UpdateHitClick(int Id, string Ip); } public class NewsService : ServiceBase<INewsRepository>, INewsService { public NewsService(IUnitOfWork _unitwork, INewsRepository _repository) : base(_unitwork, _repository) { } public void UpdateHitClick(int Id, string Ip) { base.Repository().UpdateHitClick(Id); /* var s = "update [t_News] set Visits=Visits+1,ip=:f2 whre Id=:f1"; base.Repository().CreateSQLQuery(s) .SetInt32("f1", Id) .SetString("f2", Ip) .ExecuteUpdate(); base.Repository().Commit(); */ } } }
using System; using System.Collections.Specialized; using System.Web; using System.Web.Mvc; using System.Web.Routing; using Autofac; using Job.FluenCore.Article.Mapping; using Job.FluenCore.Article.Model; using Job.FluenCore.Article.Repository; using Job.FluenCore.Article.Service; namespace Job.FluenCore.Article.Modules { public class NewsModule : Module { protected override void Load(ContainerBuilder builder) { if (builder == null) { throw new ArgumentNullException("Job.FluenCore.Article.Modules ContainerBuilder"); } builder.RegisterType<NewsService>().As<INewsService>().InstancePerLifetimeScope(); builder.RegisterType<NewsRepository>().As<INewsRepository>().InstancePerLifetimeScope(); builder.RegisterType<NewsClassService>().As<INewsClassService>().InstancePerLifetimeScope(); builder.RegisterType<NewsClassRepository>().As<INewsClassRepository>().InstancePerLifetimeScope(); base.Load(builder); } public System.Reflection.Assembly GetAssembly() { return System.Reflection.Assembly.GetExecutingAssembly(); } } }
namespace Job.FluenCore.DateFactory { public interface IRepositoryBase<T> where T : class { /// <summary> /// 提交事务 /// </summary> void Commit(); /// <summary> /// 添加 /// </summary> /// <param name="entity"></param> /// <param name="IsNowSave"></param> /// <returns></returns> T Add(T entity, bool IsNowSave = true); /// <summary> /// 更新 /// </summary> /// <param name="entity"></param> /// <param name="IsNowSave"></param> void Update(T entity, bool IsNowSave = true); void SaveOrUpdate(T entity, bool IsNowSave = true); void Delete(T entity); void Delete(int Id, bool Load = false); void Delete(Expression<Func<T, bool>> where); T GetById(int Id); T GetById(string Id); /// <summary> /// 根据条件获得模型 Linq语句 /// </summary> /// <param name="where"></param> /// <returns></returns> T Get(Expression<Func<T, bool>> where); /// <summary> /// 支持 selector where查询 /// var list= GetMany(o => o.Id > 0).Select(o => o).OrderByDescending(o=>o.AddTime).ToPagedList(pageindex, pagesize); /// </summary> T Get(Expression<Func<T, bool>> where, Expression<Func<T, T>> selector); /// <summary> /// 支持 select where orderby查询 /// var list= GetMany().Select(o => o).OrderByDescending(o=>o.AddTime).ToPagedList(pageindex, pagesize); /// </summary> IQueryable<T> GetMany(); /// <summary> /// 支持 select orderby查询 /// var list= GetMany(o => o.Id > 0).Select(o => o).OrderByDescending(o=>o.AddTime).ToPagedList(pageindex, pagesize); /// </summary> IQueryable<T> GetMany(Expression<Func<T, bool>> where); /// <summary> /// 支持 where查询 /// var list= GetList(o => o.Id > 0).Select(o => o).OrderByDescending(o=>o.AddTime).ToPagedList(pageindex, pagesize); /// </summary> PagedList<T> GetList(Expression<Func<T, bool>> where, int pagesize, int pageindex); /// <summary> /// 支持 select where查询 /// var list= GetList(o => o.Id > 0).Select(o => o).OrderByDescending(o=>o.AddTime).ToPagedList(pageindex, pagesize); /// </summary> PagedList<T> GetList(Expression<Func<T, bool>> where, Expression<Func<T, T>> select, int pagesize, int pageindex); /// <summary> /// 支持 select where查询 /// var list= GetList(o => o.Id > 0).Select(o => o).OrderByDescending(o=>o.AddTime).ToPagedList(pageindex, pagesize); /// </summary> PagedList<T> GetList(Expression<Func<T, bool>> where, Expression<Func<T, T>> select, Func<T, string> orderName, string sortOrder, int pagesize, int pageindex); /// <summary> /// 支持 select where查询 /// var list= GetForModel[T](o => o.Id > 0).Select(o => o).OrderByDescending(o=>o.AddTime).ToPagedList(pageindex, pagesize); /// </summary> IQueryable<TModel> GetForModel<TModel>(); /// <summary> /// 支持NHibernate语句,查询、更新、删除 /// eg .CreateCriteria().add(Expression.like("name", "Fritz%")).add( Expression.between("weight", minWeight, maxWeight)) /// </summary> ICriteria CreateCriteria(); /// <summary> /// 支持NHibernate语句,查询、更新、删除 /// eg .CreateCriteria().add(Expression.like("name", "Fritz%")).add( Expression.between("weight", minWeight, maxWeight)) /// </summary> ICriteria CreateCriteria(string entityName); /// <summary> /// 支持 hql,参数,查询、更新、删除\ 注意不是SQL /// hibernate 中createQuery与createSQLQuery两者区别是:前者用的hql语句进行查询,后者可以用sql语句查询| /// eg .CreateQuery("from Customer c where c.Name.Firstname=:fn and c.Name.Lastname=:ln").SetString("fn", firstname).SetString("ln", lastname) /// </summary> IQuery CreateQuery(string queryString); /// <summary> /// 支持 SQL、参数,查询、更新、删除 更新语句请加 ExecuteUpdate| /// 注意:需使用正确的 数据表结构字段 /// eg CreateSQLQuery("select ID from News where id=:f1 and IsTop>5").SetString("f1", firstname) \ /// eg CreateSQLQuery("{Call sp_Login(?,?) }").SetString(0, "admin").SetString(1, "admin"); /// </summary> ISQLQuery CreateSQLQuery(string queryString); /// <summary> /// 分页查询(sql分页方式) 统计 /// 注意:需使用正确的 数据表结构字段 /// </summary> System.Collections.Generic.IList<TModel> GetListForPaging<TModel>(string tableName, int pageNumber, int pageSize, string orderName, string sortOrder, string CommandText, out int Count); /// <summary> /// 分页查询(sql分页方式) 不统计 /// 注意:需使用正确的 数据表结构字段 /// </summary> System.Collections.Generic.IList<TModel> GetListForPaging<TModel>(string tableName, int pageNumber, int pageSize, string orderName, string sortOrder, string CommandText); /// <summary> /// 原生SQL关联查询 /// 注意:需使用正确的 数据表结构字段 /// </summary> System.Collections.Generic.IList<TModel> GetListForPaging<TModel>(string strQuery); /// <summary> /// 原生SQL关联查询 /// 注意:需使用正确的 数据表结构字段 /// </summary> System.Data.DataSet GetDataSet(string strQuery); /// <summary> /// 计算总个数(分页) /// </summary> int GetCount(string tableName, string commandText); }
using System; using System.Text; using System.Web; using System.Web.Mvc; using System.Web.Mvc.Html; using System.Linq; using System.Linq.Expressions; using System.Collections.Generic; using System.Data; using System.Data.Entity; using System.ComponentModel; using Job.FluenCore.Ceche; using Webdiyer.WebControls.Mvc; using DotNet.Common; using Job.FluenCore.Common; using Job.FluenCore.Common.MVCFormwork; using Job.FluenCore.Article; using Job.FluenCore.Article.Model; using Job.FluenCore.Article.Repository; using Job.FluenCore.Article.Service; namespace Job.Web.Controller { public class NewsController : BaseWebController { protected readonly INewsService _NewsService; protected readonly INewsClassService _NewClassService; public NewsController(INewsService NewsService, INewsClassService NewClassService) { this._NewsService = NewsService; this._NewClassService = NewClassService; } #region web [HttpGet] public virtual ActionResult Index(int? page, int intPid = 0, int intStatus = 1) { //int _page = page ?? GetPageIndex(); //var stus = (NewsClassStatusType)intStatus; //var where = PredicateExtensions.True<News>(); //if (intStatus == 0 || intStatus == 1) { where = where.And(p => p.Status == stus); } //if (intPid > 0) { where = where.And(p => p.ParentId == intPid); } //var list = _NewsService // .Repository() // .GetList(where, GetPageSize(), _page); //PageData(); return View(); } [HttpGet] public virtual ActionResult Detail(int id, int intStatus = 1) { //var data = _NewsService.Repository().GetById(id); //data = data ?? new News(); //PageData(); return View(); } #endregion #region admin /* true 显示错误; false 继续 */ [LoginAllowView] [Description("[详细信息]检查是否存在(add,Update必备)")] public ActionResult CheckExist() { var action = QueryString.Request["action"]; var ID = QueryString.Request["ID"].GetNum(0); var val = QueryString.Request[action]; var b = false; if (!val.IsNullOrWhiteSpace()) { switch (action) { case "ContentUrl": b = _NewsService.Repository().GetMany(p => p.Id != ID && p.ContentUrl == val).Any(); break; } } b = !b; return Content(b.ToString().ToLower()); } [Description("[Index主页]新闻管理")] [ViewPage] [DefaultPage] public ActionResult AdminIndex(int Type = 0) { var CurrentTypeID = Type; var titel = typeof(NewsClassType).GetEnumDictionaryA().GetValue(CurrentTypeID); titel = titel ?? "文章"; ViewBag.Title = titel + "管理"; ViewBag.CurrentID = CurrentTypeID; return View(); } [ViewPage] [Description("[详细信息]新闻详细信息(add,Update,Detail必备)")] public ActionResult AdminDetail() { ViewBag.IsView = (QueryString.Request["IsView"] == "1") ? 1 : 0; ViewBag.CurrentID = QueryString.Request["ID"].GetNum(0); return View(); } [Description("[Get Json]获取新闻Json")] [LigerUIExceptionResult] public ActionResult AdminGet(int? id) { var _id = id ?? 0; var data = _NewsService.Repository().Get(o => o.Id == _id); data = data ?? new News(); return this.JsonFormat(data, true, "获取[新闻]"); } [Description("[系统]添加动作")] [LigerUIExceptionResult] public ActionResult AdminAdd() { News model = new News(); this.TryUpdateModel(model); model.Id = 0; model.AddTime = model.AddTime == null ? DateTime.UtcNow : model.AddTime; model.EditTime = model.AddTime == null ? DateTime.UtcNow : model.EditTime; return AdminSave(model); } [Description("[系统]修改动作")] [LigerUIExceptionResult] public ActionResult AdminUpdate() { News model = new News(); this.TryUpdateModel(model); model.AddTime = model.AddTime == null ? DateTime.UtcNow : model.AddTime; model.EditTime = model.AddTime == null ? DateTime.UtcNow : model.EditTime; return AdminSave(model); } [Description("[Delete]页面删除请求")] [LigerUIExceptionResult] public ActionResult AdminDelete(int Id) { var status = true; _NewsService.Repository().Delete(Id); return this.JsonFormat(null, status, "删除[新闻]"); } [Description("[gridRequest请求]获取新闻")] [LoginAllowView] public ActionResult AdminGetGrid() { var gridRequest = new LigerUIGridRequest(HttpContext); var where = gridRequest.Where; var parms = FilterHelper.GetFilterTanslateQuery(ref where); int Count = _NewsService.Repository().GetMany() .Where(where, parms) .Count(); var data = _NewsService.Repository().GetMany() .Where(where, parms) .OrderBy(gridRequest.SortName + " " + gridRequest.SortOrder) .Skip((gridRequest.PageNumber - 1) * gridRequest.PageSize) .Take(gridRequest.PageSize) .Select(o => new { Id = o.Id, Title = o.Title, TitleColor = o.TitleColor, EditTime = o.EditTime, ContentUrl = o.ContentUrl, ContentStatus = o.ContentStatus, IndexImage = o.IndexImage, IsNoComment = o.IsNoComment, IsRecommend = o.IsRecommend, IsTop = o.IsTop, Visits = o.Visits, Star = o.Star, AddTime = o.AddTime, //TypeId = o.TypeId, ClassId = o.ClassId }) .ToList(); var grid = new LigerUIGrid(); grid.Rows = data; grid.Total = Count; return this.JsonFormat(grid); } #endregion #region heper [NonAction] public ActionResult AdminSave(News model) { var status = SaveNewsClass(model, model.Id > 1); return this.JsonFormat(null, status, "保存[新闻分类]"); } public bool SaveNewsClass(News model, bool IsEdit = true) { if (model == null) { return false; } model.AddTime = DateTimeHelper.DateTimeYeas(model.AddTime); model.EditTime = DateTimeHelper.DateTimeYeas(model.EditTime); model.ClassId = model.ClassId < 0 ? QueryString.Request["ClassId"].GetNum(0) : model.ClassId; if (IsEdit) { _NewsService.Repository().Update(model); } else { _NewsService.Repository().Add(model); } return true; } #endregion } }
同时我们对Linq的扩展也可以流畅的对数据操作。
不过这里也有一些问题需要改进;
1 目前的动态自定义查询问题,
让使用者自己可以控制查询字段、条件、显示结果字段、排序等;(特别是在管理后台,jquery + ligerUI 结合使用, 管理者可以按需查询等, )
如:
_NewsService.Repository().GetMany()
.Where("条件")
.OrderBy("id desc")
.Take(10)
.Skip(10)
.Select("New(Id,Title)");
2 跨表问题(目前可用试图、存储过程处理);
3 数据验证问题;
4 结构关系的调整处理。
未完。。。。
先下班了。。。 晚上再写。
新做的NHibernate项目,大家来拍拍砖,同时还要请多多提些问题
标签:
原文地址:http://www.cnblogs.com/shouce/p/5518626.html