Web APi之EntityFramework【CRUD】(三)
前言
之前我們系統(tǒng)學(xué)習(xí)了EntityFramework,個(gè)人覺得有些東西不能學(xué)了就算完了,必須要學(xué)以致用,在Web API上也少不了增(C)、刪(D)、改(U)、查(R)。鑒于此,我們通過EF來(lái)實(shí)現(xiàn)Web API上的增刪改查。
?
之前對(duì)于EF的基本操作都是很零散的,我們應(yīng)該對(duì)于CRUD都是通過完整封裝來(lái)實(shí)現(xiàn),并且也顯得比較專業(yè),接下來(lái)首先對(duì)EF利用Responsitory倉(cāng)儲(chǔ)模式進(jìn)行完整封裝。
?
EntityFramework完整封裝
我們建立一個(gè)Core(核心類庫(kù)),里面存放有關(guān)EF的完成封裝。
第一步
建立所有實(shí)體的基類,將實(shí)體的公共屬性放入其中,取為BaseEntity
public class BaseEntity<T>{public T Id { get; set; }}第二步
建立倉(cāng)儲(chǔ)接口IRepository,包括基本的增、刪、改、查等方法
public interface IRepository<TEntity> where TEntity : class{/// <summary>/// 獲得數(shù)據(jù)列表/// </summary>/// <returns></returns>IQueryable<TEntity> GetList();/// <summary>/// 通過id獲得實(shí)體/// </summary>/// <param name="id"></param>/// <returns></returns>TEntity GetById(object id);/// <summary>/// 添加實(shí)體/// </summary>/// <param name="entity"></param>int Insert(TEntity entity);/// <summary>/// 添加實(shí)體集合/// </summary>/// <param name="entities"></param>int Insert(IEnumerable<TEntity> entities);/// <summary>/// 刪除實(shí)體/// </summary>/// <param name="entity"></param>int Delete(TEntity entity);/// <summary>/// 根據(jù)條件刪除實(shí)體/// </summary>/// <param name="entities"></param>int DeleteByRequirement(Expression<Func<TEntity, bool>> func);/// <summary>/// 更新實(shí)體/// </summary>/// <param name="entity"></param>int Update(TEntity entity);/// <summary>/// 更新實(shí)體集合/// </summary>/// <param name="entities"></param>int Update(IEnumerable<TEntity> entities);}?
?第三步
利用倉(cāng)儲(chǔ)服務(wù)RepositoryService實(shí)現(xiàn)上述倉(cāng)儲(chǔ)接口IRepository
public class RepositoryService<TEntity> : IRepository<TEntity> where TEntity : class{private IDbContext Context;private bool IsNoTracking;/// <summary>/// 獲取實(shí)體集合/// </summary>private IDbSet<TEntity> Entities{get{return this.Context.Set<TEntity>();}}private DbEntityEntry Entry(TEntity entity){return this.Context.Entry<TEntity>(entity);}public RepositoryService(IDbContext context, bool isNoTracking){this.Context = context;this.IsNoTracking = isNoTracking;}/// <summary>/// 獲取所有數(shù)據(jù)/// </summary>/// <returns></returns>public IQueryable<TEntity> GetList(){if (!IsNoTracking)return this.Entities.AsQueryable();elsereturn this.Entities.AsNoTracking().AsQueryable();}/// <summary>/// 通過id獲取實(shí)體/// </summary>/// <param name="id"></param>/// <returns></returns>public TEntity GetById(object id){return Entities.Find(id);}/// <summary>/// 添加實(shí)體/// </summary>/// <param name="entity"></param>public int Insert(TEntity entity){Entities.Add(entity);return this.Context.SaveChanges();}public int Insert(IEnumerable<TEntity> entities){if (entities == null)throw new ArgumentNullException("entities");foreach (var entity in entities){Entities.Add(entity);}return this.Context.SaveChanges();}/// <summary>/// 刪除實(shí)體/// </summary>/// <param name="entity"></param>public int Delete(TEntity entity){if (!IsNoTracking)this.Entities.Remove(entity);elsethis.Entities.Attach(entity);this.Entities.Remove(entity);return this.Context.SaveChanges();}public int DeleteByRequirement(Expression<Func<TEntity, bool>> func){var list = GetList().Where(func).ToList();list.ForEach(e =>{if (!IsNoTracking)this.Entities.Remove(e);elsethis.Entities.Attach(e);this.Entities.Remove(e);});return this.Context.SaveChanges();}/// <summary>/// 更新實(shí)體/// </summary>/// <param name="entity"></param>public int Update(TEntity entity){if (!IsNoTracking)return this.Context.SaveChanges();elsethis.Context.Entry(entity).State = EntityState.Modified;return this.Context.SaveChanges();}public int Update(IEnumerable<TEntity> entities){if (entities == null)throw new ArgumentNullException("enetities");if (!IsNoTracking)return this.Context.SaveChanges();elseforeach (var t in entities){this.Context.Entry(t).State = EntityState.Modified;}return this.Context.SaveChanges();}/// <summary>/// 釋放資源/// </summary>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{/// <summary>/// 獲得實(shí)體集合/// </summary>/// <typeparam name="TEntity"></typeparam>/// <returns></returns>IDbSet<TEntity> Set<TEntity>() where TEntity : class;/// <summary>/// 執(zhí)行存儲(chǔ)過程/// </summary>/// <typeparam name="TEntity"></typeparam>/// <param name="commandText"></param>/// <param name="parameters"></param>/// <returns></returns>IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters)where TEntity : class;/// <summary>/// 執(zhí)行SQL語(yǔ)句查詢/// </summary>/// <typeparam name="TElement"></typeparam>/// <param name="sql"></param>/// <param name="parameters"></param>/// <returns></returns>IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters);DbEntityEntry Entry<TEntity>(TEntity entity) where TEntity : class;/// <summary>/// 保存數(shù)據(jù)/// </summary>/// <returns></returns>int SaveChanges();/// <summary>/// 變更追蹤代碼/// </summary>bool ProxyCreationEnabled { get; set; }/// <summary>/// DetectChanges方法自動(dòng)調(diào)用/// </summary>bool AutoDetectChangesEnabled { get; set; }/// <summary>/// 調(diào)用Dispose方法/// </summary>void Dispose();}第五步
實(shí)現(xiàn)EF上下文中的數(shù)據(jù)庫(kù)連接、模型初始化以及映射等(也可以手動(dòng)關(guān)閉全局變更追蹤相對(duì)比較靈活)
public class EFDbContext : DbContext, IDbContext{public EFDbContext(string connectionString): base(connectionString){ }static EFDbContext(){Database.SetInitializer<EFDbContext>(new DropCreateDatabaseIfModelChanges<EFDbContext>());}/// <summary>/// 一次性加載所有映射/// </summary>/// <param name="modelBuilder"></param>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);}/// <summary>/// 獲得實(shí)體集合/// </summary>/// <typeparam name="TEntity"></typeparam>/// <returns></returns>public new IDbSet<TEntity> Set<TEntity>() where TEntity : class{return base.Set<TEntity>();}/// <summary>/// 實(shí)體狀態(tài)/// </summary>/// <typeparam name="TEntity"></typeparam>/// <param name="entity"></param>/// <returns></returns>public new DbEntityEntry Entry<TEntity>(TEntity entity) where TEntity : class{return base.Entry<TEntity>(entity);}/// <summary>/// 執(zhí)行存儲(chǔ)過程/// </summary>/// <typeparam name="TEntity"></typeparam>/// <param name="commandText"></param>/// <param name="parameters"></param>/// <returns></returns>public IList<TEntity> ExecuteStoredProcedureList<TEntity>(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<TEntity>(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<TEntity>().Attach(result[i]);}finally{this.Configuration.AutoDetectChangesEnabled = acd;}return result;}/// <summary>/// SQL語(yǔ)句查詢/// </summary>/// <typeparam name="TElement"></typeparam>/// <param name="sql"></param>/// <param name="parameters"></param>/// <returns></returns>public IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters){return this.Database.SqlQuery<TElement>(sql, parameters);}/// <summary>/// 當(dāng)查詢或者獲取值時(shí)是否啟動(dòng)創(chuàng)建代理/// </summary>public virtual bool ProxyCreationEnabled{get{return this.Configuration.ProxyCreationEnabled;}set{this.Configuration.ProxyCreationEnabled = value;}}/// <summary>/// 當(dāng)查詢或者獲取值時(shí)指定是否開啟自動(dòng)調(diào)用DetectChanges方法/// </summary>public virtual bool AutoDetectChangesEnabled{get{return this.Configuration.AutoDetectChangesEnabled;}set{this.Configuration.AutoDetectChangesEnabled = value;}}}?以上就是對(duì)利用EntityFramework來(lái)實(shí)現(xiàn)基本操作的完整封裝。接下來(lái)就是相關(guān)類以及映射(場(chǎng)景:一個(gè)Student對(duì)應(yīng)一個(gè)Flower,而一個(gè)Flower對(duì)應(yīng)多個(gè)Student)
Student
public class Student : BaseEntity<int>{public string Name { get; set; }public int FlowerId { get; set; }public virtual Flower Flower { get; set; }}Flower
public class Flower : BaseEntity<int>{public string Remark { get; set; }public virtual ICollection<Student> Students { get; set; }}相關(guān)映射
public class StudentMap:EntityTypeConfiguration<Student>{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<Flower>{public FlowerMap(){ToTable("Flower");HasKey(p => p.Id);Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);}}CRUD?
接下來(lái)就是Web API控制器中執(zhí)行增、刪等操作,我們創(chuàng)建一個(gè)StudentController控制器,然后首先創(chuàng)建倉(cāng)儲(chǔ)服務(wù)。(執(zhí)行Action方法,依據(jù)默認(rèn)約定,未添加特性)
public IRepository<Student> _repository;public EFDbContext _ctx;public StudentController(){_ctx = new EFDbContext("DBByConnectionString");_repository = new RepositoryService<Student>(_ctx, true); //關(guān)閉局部變更追蹤}執(zhí)行R操作(即默認(rèn)請(qǐng)求到HttpGet方法)
public IEnumerable<Student> GetAllStudent(){return _repository.GetList().Select(d => new Student { Name = d.Name, Flower = d.Flower, Id = d.Id }).ToList();}當(dāng)執(zhí)行此查詢操作時(shí)卻出錯(cuò)了,真遺憾:
上述修改如下即可:
return _repository.GetList().ToList().Select(d => new Student { Name = d.Name, Flower = d.Flower, Id = d.Id }).ToList();不知道還有沒有更好的解決方案,用ToList直接將所有數(shù)據(jù)進(jìn)行加載到內(nèi)存中,在性能上消耗比較大。(期待你的解決方案)
特此記錄
在此感謝園友(_天光云影)給出的解決方案,在GetList之后利用?Linq?進(jìn)行Select,最后進(jìn)行ToList即可!!!
執(zhí)行CUD等操作
public Student GetStudentById(int id){var student = _repository.GetById(id);if (student == null)throw new HttpResponseException(HttpStatusCode.NotFound);elsereturn student;}//添加操作(HttpPost)public HttpResponseMessage PostStudent(Student stu){var insertStudent = _repository.Insert(stu);var response = Request.CreateResponse<Student>(HttpStatusCode.Created, stu);string uri = Url.Link("DefaultApi", new { id = stu.Id });response.Headers.Location = new Uri(uri);return response;}//更新操作(HttpPut)public void PutStudent(int id, Student stu){stu.Id = id;if (_repository.Update(stu) <= 0){throw new HttpResponseException(HttpStatusCode.NotFound);}}//刪除操作(HttpDelete)public void DeleteStudent(int id){Student stu = _repository.GetById(id);if (stu == null){throw new HttpResponseException(HttpStatusCode.NotFound);}_repository.Delete(stu);} View Code?總結(jié)
這節(jié)主要介紹了利用倉(cāng)儲(chǔ)模式完整封裝EF來(lái)進(jìn)行Web API基本操作,基本操作中關(guān)于返回狀態(tài)碼等信息,無(wú)非就是以下幾個(gè)對(duì)象
HttpResponseException 返回異常HttpResponseMessage 返回信息(諸如狀態(tài)碼等)HttpStatusCode 狀態(tài)碼枚舉(如頁(yè)面未找到等)?源代碼下載
【W(wǎng)ebAPI之EntityFramework】
?
轉(zhuǎn)載于:https://www.cnblogs.com/CreateMyself/p/4820121.html
總結(jié)
以上是生活随笔為你收集整理的Web APi之EntityFramework【CRUD】(三)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java记录 -38- 随机数
- 下一篇: Oracle常见操作汇总(转)