博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Web APi之EntityFramework【CRUD】(三)
阅读量:7025 次
发布时间:2019-06-28

本文共 10416 字,大约阅读时间需要 34 分钟。

前言

之前我们系统学习了EntityFramework,个人觉得有些东西不能学了就算完了,必须要学以致用,在Web API上也少不了增(C)、删(D)、改(U)、查(R)。鉴于此,我们通过EF来实现Web API上的增删改查。

 

之前对于EF的基本操作都是很零散的,我们应该对于CRUD都是通过完整封装来实现,并且也显得比较专业,接下来首先对EF利用Responsitory仓储模式进行完整封装。

 

EntityFramework完整封装

我们建立一个Core(核心类库),里面存放有关EF的完成封装。

第一步

建立所有实体的基类,将实体的公共属性放入其中,取为BaseEntity

public class BaseEntity
{ public T Id { get; set; } }

第二步

建立仓储接口IRepository,包括基本的增、删、改、查等方法

public interface IRepository
where TEntity : class { ///
/// 获得数据列表 /// ///
IQueryable
GetList(); ///
/// 通过id获得实体 /// ///
///
TEntity GetById(object id); ///
/// 添加实体 /// ///
int Insert(TEntity entity); ///
/// 添加实体集合 /// ///
int Insert(IEnumerable
entities); ///
/// 删除实体 /// ///
int Delete(TEntity entity); ///
/// 根据条件删除实体 /// ///
int DeleteByRequirement(Expression
> func); ///
/// 更新实体 /// ///
int Update(TEntity entity); ///
/// 更新实体集合 /// ///
int Update(IEnumerable
entities); }

 

 第三步

利用仓储服务RepositoryService实现上述仓储接口IRepository

public class RepositoryService
: IRepository
where TEntity : class { private IDbContext Context; private bool IsNoTracking; ///
/// 获取实体集合 /// private IDbSet
Entities { get { return this.Context.Set
(); } } private DbEntityEntry Entry(TEntity entity) { return this.Context.Entry
(entity); } public RepositoryService(IDbContext context, bool isNoTracking) { this.Context = context; this.IsNoTracking = isNoTracking; } ///
/// 获取所有数据 /// ///
public IQueryable
GetList() { if (!IsNoTracking) return this.Entities.AsQueryable(); else return this.Entities.AsNoTracking().AsQueryable(); } ///
/// 通过id获取实体 /// ///
///
public TEntity GetById(object id) { return Entities.Find(id); } ///
/// 添加实体 /// ///
public int Insert(TEntity entity) { Entities.Add(entity); return this.Context.SaveChanges(); } public int Insert(IEnumerable
entities) { if (entities == null) throw new ArgumentNullException("entities"); foreach (var entity in entities) { Entities.Add(entity); } return this.Context.SaveChanges(); } ///
/// 删除实体 /// ///
public int Delete(TEntity entity) { if (!IsNoTracking) this.Entities.Remove(entity); else this.Entities.Attach(entity); this.Entities.Remove(entity); return this.Context.SaveChanges(); } public int DeleteByRequirement(Expression
> func) { var list = GetList().Where(func).ToList(); list.ForEach(e => { if (!IsNoTracking) this.Entities.Remove(e); else this.Entities.Attach(e); this.Entities.Remove(e); }); return this.Context.SaveChanges(); } ///
/// 更新实体 /// ///
public int Update(TEntity entity) { if (!IsNoTracking) return this.Context.SaveChanges(); else this.Context.Entry(entity).State = EntityState.Modified; return this.Context.SaveChanges(); } public int Update(IEnumerable
entities) { if (entities == null) throw new ArgumentNullException("enetities"); if (!IsNoTracking) return this.Context.SaveChanges(); else foreach (var t in entities) { this.Context.Entry(t).State = EntityState.Modified; } return this.Context.SaveChanges(); } ///
/// 释放资源 /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { if (Context != null) { this.Context.Dispose(); this.Context = null; } } } }

第四步

用接口IDbContext封装EF上下文DbContext中的公共方法

public interface IDbContext    {        ///         /// 获得实体集合        ///         /// 
///
IDbSet
Set
() where TEntity : class; ///
/// 执行存储过程 /// ///
///
///
///
IList
ExecuteStoredProcedureList
(string commandText, params object[] parameters) where TEntity : class; ///
/// 执行SQL语句查询 /// ///
///
///
///
IEnumerable
SqlQuery
(string sql, params object[] parameters); DbEntityEntry Entry
(TEntity entity) where TEntity : class; ///
/// 保存数据 /// ///
int SaveChanges(); ///
/// 变更追踪代码 /// bool ProxyCreationEnabled { get; set; } ///
/// DetectChanges方法自动调用 /// bool AutoDetectChangesEnabled { get; set; } ///
/// 调用Dispose方法 /// void Dispose(); }

第五步

实现EF上下文中的数据库连接、模型初始化以及映射等(也可以手动关闭全局变更追踪相对比较灵活)

public class EFDbContext : DbContext, IDbContext    {        public EFDbContext(string connectionString)            : base(connectionString)        { }        static EFDbContext()        {            Database.SetInitializer
(new DropCreateDatabaseIfModelChanges
()); } ///
/// 一次性加载所有映射 /// ///
protected override void OnModelCreating(DbModelBuilder modelBuilder) { var typesToRegister = Assembly.GetExecutingAssembly().GetTypes() .Where(type => !String.IsNullOrEmpty(type.Namespace)) .Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>)); foreach (var type in typesToRegister) { dynamic configurationInstance = Activator.CreateInstance(type); modelBuilder.Configurations.Add(configurationInstance); } base.OnModelCreating(modelBuilder); } ///
/// 获得实体集合 /// ///
///
public new IDbSet
Set
() where TEntity : class { return base.Set
(); } ///
/// 实体状态 /// ///
///
///
public new DbEntityEntry Entry
(TEntity entity) where TEntity : class { return base.Entry
(entity); } ///
/// 执行存储过程 /// ///
///
///
///
public IList
ExecuteStoredProcedureList
(string commandText, params object[] parameters) where TEntity : class { if (parameters != null && parameters.Length > 0) { for (int i = 0; i <= parameters.Length - 1; i++) { var p = parameters[i] as DbParameter; if (p == null) throw new Exception("Not support parameter type"); commandText += i == 0 ? " " : ", "; commandText += "@" + p.ParameterName; if (p.Direction == ParameterDirection.InputOutput || p.Direction == ParameterDirection.Output) { commandText += " output"; } } } var result = this.Database.SqlQuery
(commandText, parameters).ToList(); bool acd = this.Configuration.AutoDetectChangesEnabled; try { this.Configuration.AutoDetectChangesEnabled = false; for (int i = 0; i < result.Count; i++) result[i] = this.Set
().Attach(result[i]); } finally { this.Configuration.AutoDetectChangesEnabled = acd; } return result; } ///
/// SQL语句查询 /// ///
///
///
///
public IEnumerable
SqlQuery
(string sql, params object[] parameters) { return this.Database.SqlQuery
(sql, parameters); } ///
/// 当查询或者获取值时是否启动创建代理 /// public virtual bool ProxyCreationEnabled { get { return this.Configuration.ProxyCreationEnabled; } set { this.Configuration.ProxyCreationEnabled = value; } } ///
/// 当查询或者获取值时指定是否开启自动调用DetectChanges方法 /// public virtual bool AutoDetectChangesEnabled { get { return this.Configuration.AutoDetectChangesEnabled; } set { this.Configuration.AutoDetectChangesEnabled = value; } } }

 以上就是对利用EntityFramework来实现基本操作的完整封装。接下来就是相关类以及映射(场景:一个Student对应一个Flower,而一个Flower对应多个Student)

Student

public class Student : BaseEntity
{ public string Name { get; set; } public int FlowerId { get; set; } public virtual Flower Flower { get; set; } }

Flower

public class Flower : BaseEntity
{ public string Remark { get; set; } public virtual ICollection
Students { get; set; } }

相关映射

public class StudentMap:EntityTypeConfiguration
{ public StudentMap() { ToTable("Student"); HasKey(p => p.Id); Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); HasRequired(p => p.Flower).WithMany(p => p.Students).HasForeignKey(p => p.FlowerId); } } public class FlowerMap:EntityTypeConfiguration
{ public FlowerMap() { ToTable("Flower"); HasKey(p => p.Id); Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); } }

CRUD 

接下来就是Web API控制器中执行增、删等操作,我们创建一个StudentController控制器,然后首先创建仓储服务。(执行Action方法,依据默认约定,未添加特性)

public IRepository
_repository; public EFDbContext _ctx; public StudentController() { _ctx = new EFDbContext("DBByConnectionString"); _repository = new RepositoryService
(_ctx, true); //关闭局部变更追踪 }

执行R操作(即默认请求到HttpGet方法)

public IEnumerable
GetAllStudent() { return _repository.GetList().Select(d => new Student { Name = d.Name, Flower = d.Flower, Id = d.Id }).ToList(); }

当执行此查询操作时却出错了,真遗憾:

上述修改如下即可:

return _repository.GetList().ToList().Select(d => new Student { Name = d.Name, Flower = d.Flower, Id = d.Id }).ToList();

不知道还有没有更好的解决方案,用ToList直接将所有数据进行加载到内存中,在性能上消耗比较大。(期待你的解决方案)

特此记录

在此感谢园友()给出的解决方案,在GetList之后利用 Linq 进行Select,最后进行ToList即可!!!

执行CUD等操作

 
View Code

 总结

这节主要介绍了利用仓储模式完整封装EF来进行Web API基本操作,基本操作中关于返回状态码等信息,无非就是以下几个对象

HttpResponseException  返回异常HttpResponseMessage   返回信息(诸如状态码等)HttpStatusCode       状态码枚举(如页面未找到等)

 

本文转自Jeffcky博客园博客,原文链接:http://www.cnblogs.com/CreateMyself/p/4820121.html,如需转载请自行联系原作者

你可能感兴趣的文章
.NET破解之爱奇迪(三)
查看>>
向Github提交代码时遇到的一些问题
查看>>
HttpWebRequest(跨域下载文件——网络流转换为内存流下载)
查看>>
无线路由器的些许知识
查看>>
java中集合类中Collection接口中的Map接口的常用方法熟悉
查看>>
activiti实战系列 排他网关(ExclusiveGateWay)
查看>>
maven 将jar 下载到工程当前目录下
查看>>
[Tex学习]给汉字注音
查看>>
关于fegin 没进入 fallback 以及Hystrix Dashboard 监控界面没出图形的解决方式
查看>>
如何把由js生成的内容水平居中?
查看>>
真题算法考点
查看>>
E-MapReduce集群启停HDFS/YARN服务
查看>>
Java设计模式---Builder模式
查看>>
Apache Storm源码阅读笔记&OLAP在大数据时代的挑战
查看>>
Vuejs——(7)过渡(动画)
查看>>
(二十一)java字符串替换的问题
查看>>
面向服务编程
查看>>
Codeforces Round #309 (Div. 2) B. Ohana Cleans Up
查看>>
用简单的C语言实现多任务轮流切换(模拟操作系统线程机制)
查看>>
android Recyclerview仿京东,滚动屏幕标题栏渐变(启动页面动画)
查看>>