数据访问层
数据访问层负责管理数据库与业务逻辑层之间的通讯。
下面我们以SysException单表的增删改为例,进行介绍
-
创建数据库Sys,数据库名称为"Sys",执行如下脚本
View Code
CREATE TABLE [SysException]( [Id] [nvarchar](36) NOT NULL, [LeiXing] [nvarchar](200) NULL, [Message] [nvarchar](4000) NULL, [Result] [nvarchar](200) NULL, [Remark] [nvarchar](4000) NULL, [State] [nvarchar](200) NULL, [CreateTime] [datetime] NULL, [CreatePerson] [nvarchar](200) NULL, CONSTRAINT [PK_SYSEXCEPTION] PRIMARY KEY NONCLUSTERED ( [Id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]
-
创建一个DAL的项目
在项目上添加->新建项
选择"ADO.NET 实体数据模型"
从数据库生成,新建连接
填写连接需要的数据库信息后,点击下一步
注意:只选择"在模型中加入外键列"
可以看到新生成了两个文件"App.Config"和"Model1.edmx":
"App.Config"里面是数据库连接字符串,"Model1.edmx" 里面是数据实体类和访问数据库的上下文
-
以下为代码部分:
- BaseRepository是数据访问操作的基类
View Code
using System.Linq; using System.Data; namespace Langben.DAL { public abstract class BaseRepository<T> where T : class { ///<summary> /// 获取所有 ///</summary> ///<returns>集合</returns> public virtual IQueryable<T> GetAll() { using (SysEntities db = new SysEntities()) { return GetAll(db); } } ///<summary> /// 获取所有 ///</summary> ///<returns>集合</returns> public virtual IQueryable<T> GetAll(SysEntities db) { return db.CreateObjectSet<T>().AsQueryable(); } ///<summary> /// 创建 ///</summary> ///<param name="db">实体数据</param> ///<param name="entity">将要创建的对象</param> public virtual void Create(SysEntities db, T entity) { if (entity != null) { db.CreateObjectSet<T>().AddObject(entity); } } ///<summary> /// 创建 ///</summary> ///<param name="entity">一个对象</param> ///<returns></returns> public virtual int Create(T entity) { using (SysEntities db = new SysEntities()) { Create(db, entity); return this.Save(db); } } ///<summary> /// 创建对象集合 ///</summary> ///<param name="db">实体数据</param> ///<param name="entitys">对象集合</param> public virtual void Create(SysEntities db, IQueryable<T> entitys) { foreach (var entity in entitys) { this.Create(db, entity); } } ///<summary> /// 编辑一个对象 ///</summary> ///<param name="db">实体数据</param> ///<param name="entity">将要编辑的一个对象</param> public virtual T Edit(SysEntities db, T entity) { db.CreateObjectSet<T>().Attach(entity); db.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified); return entity; } ///<summary> /// 编辑对象集合 ///</summary> ///<param name="db">实体数据</param> ///<param name="entitys">对象集合</param> public virtual void Edit(SysEntities db, IQueryable<T> entitys) { foreach (T entity in entitys) { this.Edit(db, entity); } } ///<summary> /// 提交保存,持久化到数据库 ///</summary> ///<param name="db">实体数据</param> ///<returns>受影响行数</returns> public int Save(SysEntities db) { return db.SaveChanges(); } } }
- 所有数据实体都继承自IBaseEntity接口
View Code
namespace Langben.DAL { public interface IBaseEntity { } } 业务实体(SysException)的定义和验证元数据(SysExceptionMetadata) using System; using System.ComponentModel.DataAnnotations; namespace Langben.DAL { [MetadataType(typeof(SysExceptionMetadata))]// public partial class SysException : IBaseEntity { #region 自定义属性,即由数据实体扩展的业务实体 #endregion } public class SysExceptionMetadata { [ScaffoldColumn(false)] [Display(Name = "主键", Order = 1)] public object Id { get; set; } [ScaffoldColumn(true)] [Display(Name = "类型", Order = 2)] [StringLength(200, ErrorMessage = "长度不可超过200")] public object LeiXing { get; set; } [ScaffoldColumn(true)] [Display(Name = "内容", Order = 3)] [StringLength(4000, ErrorMessage = "长度不可超过4000")] public object Message { get; set; } [ScaffoldColumn(true)] [Display(Name = "结果", Order = 4)] [StringLength(200, ErrorMessage = "长度不可超过200")] public object Result { get; set; } [ScaffoldColumn(true)] [Display(Name = "备注", Order = 5)] [StringLength(4000, ErrorMessage = "长度不可超过4000")] public object Remark { get; set; } [ScaffoldColumn(true)] [Display(Name = "状态", Order = 6)] [StringLength(200, ErrorMessage = "长度不可超过200")] public object State { get; set; } [ScaffoldColumn(true)] [Display(Name = "创建时间", Order = 7)] [DataType(DataType.DateTime,ErrorMessage="时间格式不正确")] public DateTime? CreateTime { get; set; } [ScaffoldColumn(true)] [Display(Name = "创建人", Order = 8)] [StringLength(200, ErrorMessage = "长度不可超过200")] public object CreatePerson { get; set; } } }
- 数据访问层执行数据库中的增删改操作
View Code
using System; using System.Collections.Generic; using System.Linq; using System.Data; namespace Langben.DAL { ///<summary> /// 异常处理 ///</summary> public class SysExceptionRepository : BaseRepository<SysException>,IDisposable { ///<summary> /// 通过主键id,获取异常处理---查看详细,首次编辑 ///</summary> ///<param name="id">主键</param> ///<returns>异常处理</returns> public SysException GetById(string id) { using (SysEntities db = new SysEntities()) { return GetById(db, id); } } ///<summary> /// 通过主键id,获取异常处理---查看详细,首次编辑 ///</summary> ///<param name="id">主键</param> ///<returns>异常处理</returns> public SysException GetById(SysEntities db, string id) { return db.SysException.SingleOrDefault(s => s.Id == id); } ///<summary> /// 确定删除一个对象,调用Save方法 ///</summary> ///<param name="id">一条数据的主键</param> ///<returns></returns> public int Delete(string id) { using (SysEntities db = new SysEntities()) { this.Delete(db, id); return Save(db); } } ///<summary> /// 删除一个异常处理 ///</summary> ///<param name="db">实体数据</param> ///<param name="id">一条异常处理的主键</param> public void Delete(SysEntities db, string id) { SysException deleteItem = GetById(db, id); if (deleteItem != null) { db.SysException.DeleteObject(deleteItem); } } ///<summary> /// 删除对象集合 ///</summary> ///<param name="db">实体数据</param> ///<param name="deleteCollection">主键的集合</param> public void Delete(SysEntities db, string[] deleteCollection) { //数据库设置级联关系,自动删除子表的内容 IQueryable<SysException> collection = from f in db.SysException where deleteCollection.Contains(f.Id) select f; foreach (var deleteItem in collection) { db.SysException.DeleteObject(deleteItem); } } public void Dispose() { } } }
-
我们约定:
- 将系统需要的基础类放在"Framework"文件夹中
- 所有的实体数据都需要继承IBaseEntity接口
- 所有的数据库操作都需要继承BaseRepository抽象类
- 所有的试图都需要继承BaseViewRepository抽象类
- 在数据实体上实现验证规则,对用户将来保存到数据库中的数据进行校验,保护数据的完整性
- Model1.edmx文件是Entity Framework自动生成的,不做修改,因为每次更新会覆盖。
这里使用了分部类(partial class)对实体数据SysException进行扩展,加入自定义的属性,使用SysExceptionMetadata对SysException进行数据验证。
以上我们完成了数据访问层的设计,下一章我们实现业务逻辑层的代码