EFCore+Mysql倉儲層建設
目錄結構
1.實體層(EF)搭建
1.1添加Nuget包
1.2添加實體
1.3構造DbContext
1.4數據遷移生成資料庫
2.倉儲層搭建
2.1添加Nuget包
2.2添加必要的支持IEnumerable<T>和IQueryable<T> 的OrderBy字元串支持類LinqExtensions
2.3構造RepositoryBase<T>
2.4添加Table文件夾,添加SysUserRepository
2.5添加工作單元UnitOfWork
3.WebApi項目測試
3.1注入EF
3.2測試
4.Github項目地址
正文
1.實體層(EF)搭建
新建.NetCore類庫項目Entity,本人使用的是2.0的SDK
1.1添加Nuget包
PM> Install-Package Microsoft.AspNetCore.All -version 2.0.9
PM> Install-Package Pomelo.EntityFrameworkCore.MySql -version 2.0.1
1.2添加實體
父類EntityBase
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace Entity.Table
{
public class EntityBase
{
/// <summary>
/// 創建時間
/// </summary>
[Display(Name = "創建時間")]
public DateTime? CreateTime { get; set; } = DateTime.Now;
/// <summary>
/// 創建人
/// </summary>
[Display(Name = "創建人")]
[StringLength(32)]
public string CreateUser { get; set; }
/// <summary>
/// 狀態0-刪除,1-正常,2-禁用,3-待審核
/// </summary>
[Display(Name = "狀態0-邏輯刪除,1-正常,2-禁用,...")]
public virtual int? Status { get; set; } = 2;
/// <summary>
/// 排序
/// </summary>
[Display(Name = "排序")]
public int? Sort { get; set; } = 0;
/// <summary>
/// 備註
/// </summary>
[Display(Name = "備註")]
[StringLength(200)]
public string Remark { get; set; } = "";
}
}
實體類SysUser
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
namespace Entity.Table
{
[Table("Sys_User")]
public class SysUser : EntityBase
{
[Key]
[StringLength(32)]
public string SysUserId { get; set; }
[Display(Name = "用戶名")]
[Required]
[StringLength(32)]
public string UserName { get; set; }
[Display(Name = "密碼")]
[StringLength(255)]
public string Password { get; set; }
[Display(Name = "真實姓名")]
[StringLength(32)]
public string TrueName { get; set; }
[Display(Name = "昵稱")]
[StringLength(32)]
public string NikeName { get; set; }
[Display(Name = "手機號")]
[StringLength(20)]
public string Mobile { get; set; }
[Display(Name = "郵箱")]
[EmailAddress]
[StringLength(100)]
public string Email { get; set; }
[Display(Name = "QQOpenid")]
[StringLength(200)]
public string QQ { get; set; }
[Display(Name = "微信openid")]
[StringLength(200)]
public string WX { get; set; }
[Display(Name = "頭像")]
[StringLength(255)]
public string Avatar { get; set; }
[Display(Name = "性別")]
[StringLength(1)]
public string Sex { get; set; }
[Display(Name = "用戶類型")]
[StringLength(1)]
public string UserType { get; set; }//0-前台用戶,1-管理用戶
}
}
1.3構造DbContext
using Entity.Table;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System;
namespace Entity
{
public class AeDbContext : DbContext
{
#region 構造方法
public AeDbContext(DbContextOptions<AeDbContext> options) : base(options) { }
public AeDbContext() { } //非注入構造方式
#endregion
#region 表對象
public virtual DbSet<SysUser> SysUsers { get; set; }
#endregion
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
if (!optionsBuilder.IsConfigured)
{
//重點:數據遷移或者直接New AeDbContext時候用到的鏈接字元串獲取方式
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
var configuration = builder.Build();
string connectionString = configuration.GetConnectionString("SQLConnection");
optionsBuilder.UseMySql(connectionString);
}
}
}
}
在這有重寫OnConfiguring方法,如果沒有構造資料庫鏈接字元串的話則到appsettings.json中去取,注意將appsettings.json文件始終複製
appsettings.json
{
"ConnectionStrings": {
"SQLConnection": "server=127.0.0.1;database=eftest;userid=root;pwd=123456;port=3306;sslmode=none;"
},
"server.urls": "http://localhost:5001" //監聽埠配置,可多個
}
1.4數據遷移生成資料庫
打開PM選擇默認項目Entity
輸入
PM> Add-Migration init
若提示The configuration file "appsettings.json" was not found and is not optional. The physical path is "E:VS項目EFTestEntityinDebug
etcoreapp2.0appsettings.json".
則為沒檢測到appsettings.json,需要文件更改屬性為複製
提示
後進行更新資料庫,如下為更新成功。
PM> update-database
最後Entity項目內容如下
2.倉儲層搭建
新建.NetCore類庫項目Repository並引用項目Entity
2.1添加Nuget包
PM> Install-Package Microsoft.EntityFrameworkCore -version 2.0.3
PM> Install-Package LinqKit.Microsoft.EntityFrameworkCore -version 1.1.15
2.2添加必要的支持IEnumerable<T>和IQueryable<T> 的OrderBy字元串支持類LinqExtensions
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Collections.Generic;
namespace Repository
{
internal static class LinqExtensions {
private static PropertyInfo GetPropertyInfo(Type objType, string name) {
var properties = objType.GetProperties();
var matchedProperty = properties.FirstOrDefault(p => p.Name == name);
if (matchedProperty == null) {
throw new ArgumentException("name");
}
return matchedProperty;
}
private static LambdaExpression GetOrderExpression(Type objType, PropertyInfo pi) {
var paramExpr = Expression.Parameter(objType);
var propAccess = Expression.PropertyOrField(paramExpr, pi.Name);
var expr = Expression.Lambda(propAccess, paramExpr);
return expr;
}
/// <summary>
/// 多個OrderBy用逗號隔開,屬性前面帶-號表示反序排序,exp:"name,-createtime"
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="query"></param>
/// <param name="name"></param>
/// <returns></returns>
public static IEnumerable<T> OrderByBatch<T>(this IEnumerable<T> query, string name) {
var index = 0;
var a = name.Split(",");
foreach (var item in a) {
var m = index++ > 0 ? "ThenBy" : "OrderBy";
if (item.StartsWith("-")) {
m += "Descending";
name = item.Substring(1);
} else {
name = item;
}
name = name.Trim();
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
var method = typeof(Enumerable).GetMethods().FirstOrDefault(mt => mt.Name == m && mt.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
query = (IEnumerable<T>)genericMethod.Invoke(null, new object[] { query, expr.Compile() });
}
return query;
}
/// <summary>
/// 多個OrderBy用逗號隔開,屬性前面帶-號表示反序排序,exp:"name,-createtime"
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="query"></param>
/// <param name="name"></param>
/// <returns></returns>
public static IQueryable<T> OrderByBatch<T>(this IQueryable<T> query, string name)
{
var index = 0;
var a = name.Split(",");
foreach (var item in a)
{
var m = index++ > 0 ? "ThenBy" : "OrderBy";
if (item.StartsWith("-"))
{
m += "Descending";
name = item.Substring(1);
}
else
{
name = item;
}
name = name.Trim();
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
var method = typeof(Queryable).GetMethods().FirstOrDefault(mt => mt.Name == m && mt.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
query = (IQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
}
return query;
}
/// <summary>
/// 正序排序單個
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="query"></param>
/// <param name="name"></param>
/// <returns></returns>
public static IQueryable<T> OrderBy<T>(this IQueryable<T> query, string name) {
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
var method = typeof(Queryable).GetMethods().FirstOrDefault(m => m.Name == "OrderBy" && m.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
return (IQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
}
/// <summary>
/// 正序排序單個(非首個)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="query"></param>
/// <param name="name"></param>
/// <returns></returns>
public static IQueryable<T> ThenBy<T>(this IQueryable<T> query, string name)
{
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
var method = typeof(Queryable).GetMethods().FirstOrDefault(m => m.Name == "ThenBy" && m.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
return (IQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
}
/// <summary>
/// 反序排序單個
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="query"></param>
/// <param name="name"></param>
/// <returns></returns>
public static IQueryable<T> OrderByDescending<T>(this IQueryable<T> query, string name)
{
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
var metMethods = typeof(Queryable).GetMethods();
var method = metMethods.FirstOrDefault(m => m.Name == "OrderByDescending" && m.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
return (IQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
}
/// <summary>
/// 反序排序單個(非首個)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="query"></param>
/// <param name="name"></param>
/// <returns></returns>
public static IQueryable<T> ThenByDescending<T>(this IQueryable<T> query, string name)
{
var propInfo = GetPropertyInfo(typeof(T), name);
var expr = GetOrderExpression(typeof(T), propInfo);
var metMethods = typeof(Queryable).GetMethods();
var method = metMethods.FirstOrDefault(m => m.Name == "ThenByDescending" && m.GetParameters().Length == 2);
var genericMethod = method.MakeGenericMethod(typeof(T), propInfo.PropertyType);
return (IQueryable<T>)genericMethod.Invoke(null, new object[] { query, expr });
}
}
}
以及分頁支持類PageData<T>
using System;
using System.Collections.Generic;
using System.Text;
namespace Repository
{
public class PageData<T>
{
public List<T> Rows { get; set; }
public long Totals { get; set; }
}
}
2.3構造RepositoryBase<T>
using Entity;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Infrastructure;
using System.IO;
using Entity.Table;
namespace Repository
{
public class RepositoryBase<T> where T : EntityBase
{
private readonly DbSet<T> _dbSet;
public AeDbContext DbContext { get; } = null;
public RepositoryBase(AeDbContext context)
{
DbContext = context;
_dbSet = DbContext.Set<T>();
}
public DatabaseFacade Database => DbContext.Database;
public IQueryable<T> Entities => _dbSet.AsQueryable().AsNoTracking();
public int SaveChanges()
{
return DbContext.SaveChanges();
}
public async Task<int> SaveChangesAsync()
{
return await DbContext.SaveChangesAsync();
}
public bool Any(Expression<Func<T, bool>> whereLambd)
{
return _dbSet.Where(whereLambd).Any();
}
public void Disposed()
{
throw new Exception("不允許在這裡釋放上下文,請在UnitOfWork中操作");
//DbContext.Dispose();
}
#region 插入數據
public bool Insert(T entity, bool isSaveChange = true)
{
_dbSet.Add(entity);
if (isSaveChange)
{
return SaveChanges() > 0;
}
return false;
}
public async Task<bool> InsertAsync(T entity, bool isSaveChange = true)
{
_dbSet.Add(entity);
if (isSaveChange)
{
return await SaveChangesAsync() > 0;
}
return false;
}
public bool Insert(List<T> entitys, bool isSaveChange = true)
{
_dbSet.AddRange(entitys);
if (isSaveChange)
{
return SaveChanges() > 0;
}
return false;
}
public async Task<bool> InsertAsync(List<T> entitys, bool isSaveChange = true)
{
_dbSet.AddRange(entitys);
if (isSaveChange)
{
return await SaveChangesAsync() > 0;
}
return false;
}
#endregion
#region 刪除
public bool Delete(T entity, bool isSaveChange = true)
{
_dbSet.Attach(entity);
_dbSet.Remove(entity);
return isSaveChange ? SaveChanges() > 0 : false;
}
public bool Delete(List<T> entitys, bool isSaveChange = true)
{
entitys.ForEach(entity =>
{
_dbSet.Attach(entity);
_dbSet.Remove(entity);
});
return isSaveChange ? SaveChanges() > 0 : false;
}
public virtual async Task<bool> DeleteAsync(T entity, bool isSaveChange = true)
{
_dbSet.Attach(entity);
_dbSet.Remove(entity);
return isSaveChange ? await SaveChangesAsync() > 0 : false;
}
public virtual async Task<bool> DeleteAsync(List<T> entitys, bool isSaveChange = true)
{
entitys.ForEach(entity =>
{
_dbSet.Attach(entity);
_dbSet.Remove(entity);
});
return isSaveChange ? await SaveChangesAsync() > 0 : false;
}
#endregion
#region 更新數據
public bool Update(T entity, bool isSaveChange = true, List<string> updatePropertyList = null, bool modified = true)
{
if (entity == null)
{
return false;
}
_dbSet.Attach(entity);
var entry = DbContext.Entry(entity);
if (updatePropertyList == null)
{
entry.State = EntityState.Modified;//全欄位更新
}
else
{
if (modified)
{
updatePropertyList.ForEach(c => {
entry.Property(c).IsModified = true; //部分欄位更新的寫法
});
}
else
{
entry.State = EntityState.Modified;//全欄位更新
updatePropertyList.ForEach(c => {
entry.Property(c).IsModified = false; //部分欄位不更新的寫法
});
}
}
if (isSaveChange)
{
return SaveChanges() > 0;
}
return false;
}
public bool Update(List<T> entitys, bool isSaveChange = true)
{
if (entitys == null || entitys.Count == 0)
{
return false;
}
entitys.ForEach(c => {
Update(c, false);
});
if (isSaveChange)
{
return SaveChanges() > 0;
}
return false;
}
public async Task<bool> UpdateAsync(T entity, bool isSaveChange = true, List<string> updatePropertyList = null, bool modified = true)
{
if (entity == null)
{
return false;
}
_dbSet.Attach(entity);
var entry = DbContext.Entry<T>(entity);
if (updatePropertyList == null)
{
entry.State = EntityState.Modified;//全欄位更新
}
else
{
if (modified)
{
updatePropertyList.ForEach(c => {
entry.Property(c).IsModified = true; //部分欄位更新的寫法
});
}
else
{
entry.State = EntityState.Modified;//全欄位更新
updatePropertyList.ForEach(c => {
entry.Property(c).IsModified = false; //部分欄位不更新的寫法
});
}
}
if (isSaveChange)
{
return await SaveChangesAsync() > 0;
}
return false;
}
public async Task<bool> UpdateAsync(List<T> entitys, bool isSaveChange = true)
{
if (entitys == null || entitys.Count == 0)
{
return false;
}
entitys.ForEach(c => {
_dbSet.Attach(c);
DbContext.Entry<T>(c).State = EntityState.Modified;
});
if (isSaveChange)
{
return await SaveChangesAsync() > 0;
}
return false;
}
#endregion
#region 查找
public long Count(Expression<Func<T, bool>> predicate = null)
{
if (predicate == null)
{
predicate = c => true;
}
return _dbSet.LongCount(predicate);
}
public async Task<long> CountAsync(Expression<Func<T, bool>> predicate = null)
{
if (predicate == null)
{
predicate = c => true;
}
return await _dbSet.LongCountAsync(predicate);
}
public T Get(object id)
{
if (id == null)
{
return default(T);
}
return _dbSet.Find(id);
}
public T Get(Expression<Func<T, bool>> predicate = null, bool isNoTracking = true)
{
var data = isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate);
return data.FirstOrDefault();
}
public async Task<T> GetAsync(object id)
{
if (id == null)
{
return default(T);
}
return await _dbSet.FindAsync(id);
}
public async Task<T> GetAsync(Expression<Func<T, bool>> predicate = null, bool isNoTracking = true)
{
var data = isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate);
return await data.FirstOrDefaultAsync();
}
public async Task<List<T>> GetListAsync(Expression<Func<T, bool>> predicate = null, string ordering = "", bool isNoTracking = true)
{
var data = isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate);
if (!string.IsNullOrEmpty(ordering))
{
data = data.OrderByBatch(ordering);
}
return await data.ToListAsync();
}
public List<T> GetList(Expression<Func<T, bool>> predicate = null, string ordering = "", bool isNoTracking = true)
{
var data = isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate);
if (!string.IsNullOrEmpty(ordering))
{
data = data.OrderByBatch(ordering);
}
return data.ToList();
}
public async Task<IQueryable<T>> LoadAsync(Expression<Func<T, bool>> predicate = null, bool isNoTracking = true)
{
if (predicate == null)
{
predicate = c => true;
}
return await Task.Run(() => isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate));
}
public IQueryable<T> Load(Expression<Func<T, bool>> predicate = null, bool isNoTracking = true)
{
if (predicate == null)
{
predicate = c => true;
}
return isNoTracking ? _dbSet.Where(predicate).AsNoTracking() : _dbSet.Where(predicate);
}
#region 分頁查找
/// <summary>
/// 分頁查詢非同步
/// </summary>
/// <param name="whereLambda">查詢添加(可有,可無)</param>
/// <param name="ordering">排序條件(一定要有)</param>
/// <param name="pageIndex">當前頁碼</param>
/// <param name="pageSize">每頁大小</param>
/// <param name="isOrder">排序正反</param>
/// <returns></returns>
public async Task<PageData<T>> GetPageAsync<TKey>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, TKey>> orderBy, int pageIndex, int pageSize, bool isOrder = true, bool isNoTracking = true)
{
IQueryable<T> data = isOrder ?
_dbSet.OrderBy(orderBy) :
_dbSet.OrderByDescending(orderBy);
if (whereLambda != null)
{
data = isNoTracking ? data.Where(whereLambda).AsNoTracking() : data.Where(whereLambda);
}
PageData<T> pageData = new PageData<T>
{
Totals = await data.CountAsync(),
Rows = await data.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync()
};
return pageData;
}
/// <summary>
/// 分頁查詢非同步
/// </summary>
/// <param name="whereLambda">查詢添加(可有,可無)</param>
/// <param name="ordering">排序條件(一定要有,多個用逗號隔開,倒序開頭用-號)</param>
/// <param name="pageIndex">當前頁碼</param>
/// <param name="pageSize">每頁大小</param>
/// <returns></returns>
public async Task<PageData<T>> GetPageAsync(Expression<Func<T, bool>> whereLambda, string ordering, int pageIndex, int pageSize, bool isNoTracking = true)
{
// 分頁 一定注意: Skip 之前一定要 OrderBy
if (string.IsNullOrEmpty(ordering))
{
ordering = nameof(T) + "Id";//默認以Id排序
}
var data = _dbSet.OrderByBatch(ordering);
if (whereLambda != null)
{
data = isNoTracking ? data.Where(whereLambda).AsNoTracking() : data.Where(whereLambda);
}
//查看生成的sql,找到大數據下分頁巨慢原因為order by 耗時
//var sql = data.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToSql();
//File.WriteAllText(@"D:sql.txt",sql);
PageData<T> pageData = new PageData<T>
{
Totals = await data.CountAsync(),
Rows = await data.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync()
};
return pageData;
}
/// <summary>
/// 分頁查詢
/// </summary>
/// <param name="whereLambda">查詢添加(可有,可無)</param>
/// <param name="ordering">排序條件(一定要有,多個用逗號隔開,倒序開頭用-號)</param>
/// <param name="pageIndex">當前頁碼</param>
/// <param name="pageSize">每頁大小</param>
/// <returns></returns>
public PageData<T> GetPage(Expression<Func<T, bool>> whereLambda, string ordering, int pageIndex, int pageSize, bool isNoTracking = true)
{
// 分頁 一定注意: Skip 之前一定要 OrderBy
if (string.IsNullOrEmpty(ordering))
{
ordering = nameof(T) + "Id";//默認以Id排序
}
var data = _dbSet.OrderByBatch(ordering);
if (whereLambda != null)
{
data = isNoTracking ? data.Where(whereLambda).AsNoTracking() : data.Where(whereLambda);
}
PageData<T> pageData = new PageData<T>
{
Totals = data.Count(),
Rows = data.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList()
};
return pageData;
}
#endregion
#endregion
}
}
2.4添加Table文件夾,添加SysUserRepository
using Entity;
using Entity.Table;
using System;
using System.Collections.Generic;
using System.Text;
namespace Repository.Table
{
public class SysUserRepository : RepositoryBase<SysUser>
{
public SysUserRepository(AeDbContext context) : base(context)
{
}
}
}
2.5添加工作單元UnitOfWork
using Entity;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Repository.Table;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Repository
{
public class UnitOfWork : IDisposable
{
public static UnitOfWork Instance = new UnitOfWork(new AeDbContext());
public AeDbContext DbContext { get; set; } = null;
public UnitOfWork(AeDbContext dbContext)
{
DbContext = dbContext;
}
#region 欄位
private SysUserRepository _SysUserRepository = null;
#endregion
#region 操作類屬性
public SysUserRepository SysUserRepository => _SysUserRepository ?? (_SysUserRepository = new SysUserRepository(DbContext));
#endregion
#region 倉儲操作(提交事務保存SaveChanges(),回滾RollBackChanges(),釋放資源Dispose())
/// <summary>
/// 保存
/// </summary>
public int SaveChanges()
{
return DbContext.SaveChanges();
}
public async Task<int> SaveChangesAsync()
{
return await DbContext.SaveChangesAsync();
}
/// <summary>
/// 回滾
/// </summary>
public void RollBackChanges()
{
var items = DbContext.ChangeTracker.Entries().ToList();
items.ForEach(o => o.State = EntityState.Unchanged);
}
/// <summary>
/// 釋放資源
/// </summary>
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
DbContext.Dispose();//隨著工作單元的銷毀而銷毀
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public IDbContextTransaction BeginTransaction()
{
var scope = DbContext.Database.BeginTransaction();
return scope;
}
#endregion
}
}
這樣倉儲層就構造完成了,篇幅已經很長了,Service層就先不介紹了。
3.WebApi項目測試
新建.NetCore的項目的Web應用程序ApiTest,選擇webapi方式,並引用Entity和Repository項目
3.1注入EF
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<AeDbContext>(options => options.UseMySql(Configuration.GetConnectionString("SQLConnection")));
services.AddTransient(typeof(UnitOfWork));//注入工作單元
}
3.2測試
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Repository;
namespace ApiTest.Controllers
{
[Route("api/[controller]")]
public class ValuesController : Controller
{
UnitOfWork _unitOfWork;
public ValuesController(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
var adminModel = _unitOfWork.SysUserRepository.Get("admin");
if(adminModel == null)
{
adminModel = new Entity.Table.SysUser()
{
SysUserId = "admin",
UserName = "admin",
Password = "123456",
UserType = "1",
CreateTime = DateTime.Now,
Status = 1,
Sort = 0
};
_unitOfWork.SysUserRepository.Insert(adminModel);
}
return new List<string> { adminModel.UserName , adminModel.Password };
}
// GET api/values/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody]string value)
{
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
}
}
}
測試結果:
4.Github項目地址
最後附上github源碼:https://github.com/atorzhang/EFTest
作者:jomz
原文地址:https://www.cnblogs.com/jomzhang/p/10245077.html
※漫談:htts是如何保證一台主機把數據安全發給另一台主機
※mysql+mycat實現主從複製、讀寫分離
TAG:程序員小新人學習 |