.Net Core2.2 + EF Core + DI,三層框架項目搭建教程


筆記:

  近兩年.Net Core發展的很快,目前最新版為3.0預覽版,之前在網上買了一本1.1版書籍都還沒來得及看呢,估計現在拿出來看也毫無意義了。已多年.net工作經驗,看書不如直接實際上手來得快,遇到問題再度娘吧。正好最近公司不忙時,抽空親手搭建.Net Core項目熟悉一下,說起.net那最自豪的就是VS編譯器了,強大的輔助功能很多中小型項目只需要下一步就可以創建完成。這里我們還需要簡單封裝一下,使用倉儲模式對數據訪問層封裝和Service層封裝,通過.net自帶DI依賴注入進行創建對象。對於初學者的我只能簡單的封裝一下,接下來我會一一講解框架的思路,如有更好的方案或不明的地方歡迎留言。轉載請備注來源:https://www.cnblogs.com/han1982/p/11058788.html

下面是已搭建好的框架結構:

 

第一步:創建解決方案

使用Visual Studio 2019編譯器創建解決方案,默認安裝vs2019自帶的.NET Core 2.1,創建.NET Core 2.2版需要下載SDK安裝。

https://dotnet.microsoft.com/download/visual-studio-sdks?utm_source=getdotnetsdk&utm_medium=referral

接下來可以創建項目了,首先創建的是數據訪問層,我們命名為common.Core,另外給他創建一個接口層common.Interface。

 

(注意所有程序集創建必須為.Net Core版,為以后發布垮平台考慮)

第二步:創建Model層

封裝倉儲層之前先來創建數據Model層,Nuget添加EF Core相關引用,工具 - NuGet包管理器 - 程序包管理器控制台,默認項目選擇Model程序集依次安裝以下組件包。

Install-Package Microsoft.EntityFrameworkCore -version 2.2.4

Install-Package Microsoft.EntityFrameworkCore.SqlServer -version 2.2.4

Install-Package Microsoft.EntityFrameworkCore.Tools -version 2.2.4

也可以在項目中找到依賴項,右鍵管理NuGet管理包方式進行添加。

 

Microsoft.EntityFrameworkCore.Tools中包含了Microsoft.EntityFrameworkCore.Design依賴包,不需要單獨安裝了。

這里我使用的是Database First模式,使用工具Scaffold-DbContext(數據庫上下文腳手架)來生成model類文件和DbContext。

執行以下命令:-o (OutputDir) 指定用於輸出類的目錄  -f (Force) 生成時覆蓋現有文件 -Context 指定生成的DbContext類的名稱,省略的話按數據庫名稱生成DbContext類文件。

Scaffold-DbContext "server=.;database=ConCard;uid=sa;pwd=123123;" Microsoft.EntityFrameworkCore.SqlServer -O Models -F

出現錯誤:VS2019有個小小BUG,默認項目選中以后最終執行的不是被選中程序集,這里需要把model程序集設為啟動項目,再次執行。

自動生成所有類模型文件,ConCardContext.cs數據庫上下文也都幫你創建好了,這樣就省去了我們手動寫DBSet時間。

第三步:封裝數據訪問層

數據訪問層主要封裝倉儲Repository和工作單元UnitOfWork,我把這兩個合並到一個類中實現,通過簡單工廠方式創建實例對象。

我們直接把ConCardContext.cs這個類復制到common.Core程序集中,把命名空間修改為common.Core。

這時應該報錯,因為common.Core項目中沒有引用EFCore依賴包,按之前Model層添加一樣,使用Install-Package命令為common.Core添加依賴包,Tools可以不用安裝。

依賴項中,右鍵添加引用,把Model和common.Interface項目引用,ConCardContext.cs中using model就不會報錯了。

接下來修改下ConCardContext:

重寫SaveChanges()方法

public override int SaveChanges()
{
    return base.SaveChanges(true);
}

刪除OnConfiguring()方法,因為我們不需要在這里配置數據庫連接,后面通過讀取配置方式設置。

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
        optionsBuilder.UseSqlServer("server=.;database=ConCard;uid=sa;pwd=123123;");
     }
}

common.Interface程序集中創建IconcardContext接口,ConCardContext類中繼承自這個接口。(主要用來后期使用DI依賴注入使用,不用接口也可以用DbContext代替)

ConCardContext類:

using System;
using com.Synjones.Model.Models;
using common.Interface;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;

namespace common.Core
{
    public partial class ConCardContext : DbContext, IconcardContext
    {
        public ConCardContext()
        {
        }

        public ConCardContext(DbContextOptions<ConCardContext> options)
            : base(options)
        {
        }

        public override int SaveChanges()
        {
            return base.SaveChanges(true);
        }

        public virtual DbSet<Admin> Admin { get; set; }
        public virtual DbSet<User> User { get; set; }


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");

            modelBuilder.Entity<Admin>(entity =>
            {
                entity.Property(e => e.PassWord).HasMaxLength(50);

                entity.Property(e => e.UserId).HasMaxLength(50);
            });

            modelBuilder.Entity<User>(entity =>
            {
                entity.Property(e => e.Name).HasMaxLength(50);

                entity.Property(e => e.Phone).HasMaxLength(50);
            });
        }
    }
}
View Code

開始繼續創建Repository.cs倉儲類,它是一個泛型類,並且擁有一個帶有參數的構造方法,通過構造方法獲得當前DbContext上下文對象,泛型類為指定Model類型,通過DbContext.Set<T>()方法最終得到相應的DbSet<T>對象來操作工作單元。

當然我們也要給他定義一個接口IRepository接口:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace common.Interface
{
    public interface IRepository<T> : IDisposable where T : class
    {
        /// <summary>
        /// 顯式開啟數據上下文事務
        /// </summary>
        /// <param name="isolationLevel">指定連接的事務鎖定行為</param>
        void BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified);

        /// <summary>
        /// 提交事務的更改
        /// </summary>
        void Commit();

        /// <summary>
        /// 顯式回滾事務,僅在顯式開啟事務后有用
        /// </summary>
        void Rollback();

        /// <summary>
        /// 提交當前單元操作的更改
        /// </summary>
        int SaveChanges();

        /// <summary>
        /// 獲取 當前實體類型的查詢數據集,數據將使用不跟蹤變化的方式來查詢,當數據用於展現時,推薦使用此數據集,如果用於新增,更新,刪除時,請使用<see cref="TrackEntities"/>數據集
        /// </summary>
        IQueryable<T> Entities { get; }

        /// <summary>
        /// 獲取 當前實體類型的查詢數據集,當數據用於新增,更新,刪除時,使用此數據集,如果數據用於展現,推薦使用<see cref="Entities"/>數據集
        /// </summary>
        IQueryable<T> TrackEntities { get; }

        /// <summary>
        /// 插入 - 通過實體對象添加
        /// </summary>
        /// <param name="entity">實體對象</param>
        /// <param name="isSave">是否執行</param>
        /// /// <returns></returns>
        T Add(T entity, bool isSave = true);

        /// <summary>
        /// 批量插入 - 通過實體對象集合添加
        /// </summary>
        /// <param name="entitys">實體對象集合</param>
        /// <param name="isSave">是否執行</param>
        void AddRange(IEnumerable<T> entitys, bool isSave = true);

        /// <summary>
        /// 刪除 - 通過實體對象刪除
        /// </summary>
        /// <param name="entity">實體對象</param>
        /// <param name="isSave">是否執行</param>
        void Delete(T entity, bool isSave = true);

        /// <summary>
        /// 批量刪除 - 通過實體對象集合刪除
        /// </summary>
        /// <param name="entitys">實體對象集合</param>
        /// <param name="isSave">是否執行</param>
        void Delete(bool isSave = false, params T[] entitys);

        /// <summary>
        /// 刪除 - 通過主鍵ID刪除
        /// </summary>
        /// <param name="id">主鍵ID</param>
        /// <param name="isSave">是否執行</param>
        void Delete(object id, bool isSave = true);

        /// <summary>
        /// 批量刪除 - 通過條件刪除
        /// </summary>
        /// <param name="where">過濾條件</param>
        /// <param name="isSave">是否執行</param>
        void Delete(Expression<Func<T, bool>> @where, bool isSave = true);

        /// <summary>
        /// 修改 - 通過實體對象修改
        /// </summary>
        /// <param name="entity">實體對象</param>
        /// <param name="isSave"></param>
        void Update(T entity, bool isSave = true);

        /// <summary>
        /// 批量修改 - 通過實體對象集合修改
        /// </summary>
        /// <param name="entitys">實體對象集合</param>
        /// <param name="isSave"></param>
        void Update(bool isSave = true, params T[] entitys);

        /// <summary>
        /// 是否滿足條件
        /// </summary>
        /// <param name="where">過濾條件</param>
        /// <returns></returns>
        bool Any(Expression<Func<T, bool>> @where);

        /// <summary>
        /// 返回總條數
        /// </summary>
        /// <returns></returns>
        int Count();

        /// <summary>
        /// 返回總條數 - 通過條件過濾
        /// </summary>
        /// <param name="where">過濾條件</param>
        /// <returns></returns>
        int Count(Expression<Func<T, bool>> @where);

        /// <summary>
        /// 返回第一條記錄
        /// </summary>
        /// <param name="where">過濾條件</param>
        /// <returns></returns>
        T FirstOrDefault(Expression<Func<T, bool>> @where);

        /// <summary>
        /// 返回第一條記錄 - 通過條件過濾
        /// </summary>
        /// <typeparam name="TOrder">排序約束</typeparam>
        /// <param name="where">過濾條件</param>
        /// <param name="order">排序條件</param>
        /// <param name="isDesc">排序方式</param>
        /// <returns></returns>
        T FirstOrDefault<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, bool isDesc = false);

        /// <summary>
        /// 去重查詢
        /// </summary>
        /// <param name="where">過濾條件</param>
        /// <returns></returns>
        IQueryable<T> Distinct(Expression<Func<T, bool>> @where);

        /// <summary>
        /// 條件查詢
        /// </summary>
        /// <param name="where">過濾條件</param>
        /// <returns></returns>
        IQueryable<T> Where(Expression<Func<T, bool>> @where);

        /// <summary>
        /// 條件查詢 - 支持排序
        /// </summary>
        /// <typeparam name="TOrder">排序約束</typeparam>
        /// <param name="where">過濾條件</param>
        /// <param name="order">排序條件</param>
        /// <param name="isDesc">排序方式</param>
        /// <returns></returns>
        IQueryable<T> Where<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, bool isDesc = false);

        /// <summary>
        /// 條件分頁查詢 - 支持排序
        /// </summary>
        /// <typeparam name="TOrder">排序約束</typeparam>
        /// <param name="where">過濾條件</param>
        /// <param name="order">排序條件</param>
        /// <param name="pageIndex">當前頁碼</param>
        /// <param name="pageSize">每頁記錄條數</param>
        /// <param name="count">返回總條數</param>
        /// <param name="isDesc">是否倒序</param>
        /// <returns></returns>
        IEnumerable<T> Where<TOrder>(Func<T, bool> @where, Func<T, TOrder> order, int pageIndex, int pageSize, out int count, bool isDesc = false);

        /// <summary>
        /// 條件分頁查詢 - 支持排序 - 支持Select導航屬性查詢
        /// </summary>
        /// <typeparam name="TOrder">排序約束</typeparam>
        /// <param name="where">過濾條件</param>
        /// <param name="order">排序條件</param>
        /// <param name="pageIndex">當前頁碼</param>
        /// <param name="pageSize">每頁記錄條數</param>
        /// <param name="count">返回總條數</param>
        /// <param name="isDesc">是否倒序</param>
        /// <returns></returns>
        IQueryable<T> Where<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, int pageIndex, int pageSize, out int count, bool isDesc = false);

        /// <summary>
        /// 獲取所有數據
        /// </summary>
        /// <returns></returns>
        IQueryable<T> GetAll();

        /// <summary>
        /// 獲取所有數據 - 支持排序
        /// </summary>
        /// <typeparam name="TOrder">排序約束</typeparam>
        /// <param name="order">排序條件</param>
        /// <param name="isDesc">排序方式</param>
        /// <returns></returns>
        IQueryable<T> GetAll<TOrder>(Expression<Func<T, TOrder>> order, bool isDesc = false);

        /// <summary>
        /// 根據ID查詢
        /// </summary>
        /// <typeparam name="Ttype">字段類型</typeparam>
        /// <param name="id">主鍵ID</param>
        /// <returns></returns>
        T GetById<Ttype>(Ttype id);

        /// <summary>
        /// 獲取最大值
        /// </summary>
        /// <typeparam name="Ttype">字段類型</typeparam>
        /// <param name="column">字段條件</param>
        /// <returns></returns>
        Ttype Max<Ttype>(Expression<Func<T, Ttype>> column);

        /// <summary>
        /// 獲取最大值
        /// </summary>
        /// <typeparam name="Ttype">字段類型</typeparam>
        /// <param name="column">字段條件</param>
        /// <param name="where">過濾條件</param>
        /// <returns></returns>
        Ttype Max<Ttype>(Expression<Func<T, Ttype>> column, Expression<Func<T, bool>> @where);

        /// <summary>
        /// 獲取最小值
        /// </summary>
        /// <typeparam name="Ttype">字段類型</typeparam>
        /// <param name="column">字段條件</param>
        /// <returns></returns>
        Ttype Min<Ttype>(Expression<Func<T, Ttype>> column);

        /// <summary>
        /// 獲取最小值
        /// </summary>
        /// <typeparam name="Ttype">字段類型</typeparam>
        /// <param name="column">字段條件</param>
        /// <param name="where">過濾條件</param>
        /// <returns></returns>
        Ttype Min<Ttype>(Expression<Func<T, Ttype>> column, Expression<Func<T, bool>> @where);

        /// <summary>
        /// 獲取總數
        /// </summary>
        /// <typeparam name="TType">字段類型</typeparam>
        /// <param name="selector">字段條件</param>
        /// <param name="where">過濾條件</param>
        /// <returns></returns>
        TType Sum<TType>(Expression<Func<T, TType>> selector, Expression<Func<T, bool>> @where) where TType : new();
    }
}
View Code

Repository類,實現了CRUD基本功能的封裝:

using common.Interface;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace common.Core
{
    public class Repository<T> : IRepository<T> where T : class
    {
        private ConCardContext _dbContext;
        private readonly DbSet<T> _dbSet;
        private readonly string _connStr;

        public Repository(IconcardContext mydbcontext)
        {
            this._dbContext = mydbcontext as ConCardContext;
            this._dbSet = _dbContext.Set<T>();
            this._connStr = _dbContext.Database.GetDbConnection().ConnectionString;
        }

        public void BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified)
        {
            if (this._dbContext.Database.CurrentTransaction == null)
            {
                this._dbContext.Database.BeginTransaction(isolationLevel);
            }
        }

        public void Commit()
        {
            var transaction = this._dbContext.Database.CurrentTransaction;
            if (transaction != null)
            {
                try
                {
                    transaction.Commit();
                }
                catch (Exception)
                {
                    transaction.Rollback();
                    throw;
                }
            }
        }

        public void Rollback()
        {
            if (this._dbContext.Database.CurrentTransaction != null)
            {
                this._dbContext.Database.CurrentTransaction.Rollback();
            }
        }

        public int SaveChanges()
        {
            return this._dbContext.SaveChanges();
        }


        public IQueryable<T> Entities
        {
            get { return this._dbSet.AsNoTracking(); }
        }

        public IQueryable<T> TrackEntities
        {
            get { return this._dbSet; }
        }

        public T Add(T entity, bool isSave = true)
        {
            this._dbSet.Add(entity);
            if (isSave)
            {
                this.SaveChanges();
            }
            return entity;
        }

        public void AddRange(IEnumerable<T> entitys, bool isSave = true)
        {
            this._dbSet.AddRange(entitys);
            if (isSave)
            {
                this.SaveChanges();
            }
        }

        public void Delete(T entity, bool isSave = true)
        {
            this._dbSet.Remove(entity);
            if (isSave)
            {
                this.SaveChanges();
            }
        }

        public void Delete(bool isSave = true, params T[] entitys)
        {
            this._dbSet.RemoveRange(entitys);
            if (isSave)
            {
                this.SaveChanges();
            }
        }

        public void Delete(object id, bool isSave = true)
        {
            this._dbSet.Remove(this._dbSet.Find(id));
            if (isSave)
            {
                this.SaveChanges();
            }
        }

        public void Delete(Expression<Func<T, bool>> @where, bool isSave = true)
        {
            T[] entitys = this._dbSet.Where<T>(@where).ToArray();
            if (entitys.Length > 0)
            {
                this._dbSet.RemoveRange(entitys);
            }
            if (isSave)
            {
                this.SaveChanges();
            }
        }

        public void Update(T entity, bool isSave = true)
        {
            var entry = this._dbContext.Entry(entity);
            if (entry.State == EntityState.Detached)
            {
                entry.State = EntityState.Modified;
            }
            if (isSave)
            {
                this.SaveChanges();
            }
        }

        public void Update(bool isSave = true, params T[] entitys)
        {
            var entry = this._dbContext.Entry(entitys);
            if (entry.State == EntityState.Detached)
            {
                entry.State = EntityState.Modified;
            }
            if (isSave)
            {
                this.SaveChanges();
            }
        }

        public bool Any(Expression<Func<T, bool>> @where)
        {
            return this._dbSet.AsNoTracking().Any(@where);
        }

        public int Count()
        {
            return this._dbSet.AsNoTracking().Count();
        }

        public int Count(Expression<Func<T, bool>> @where)
        {
            return this._dbSet.AsNoTracking().Count(@where);
        }

        public T FirstOrDefault(Expression<Func<T, bool>> @where)
        {
            return this._dbSet.AsNoTracking().FirstOrDefault(@where);
        }

        public T FirstOrDefault<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, bool isDesc = false)
        {
            if (isDesc)
            {
                return this._dbSet.AsNoTracking().OrderByDescending(order).FirstOrDefault(@where);
            }
            else
            {
                return this._dbSet.AsNoTracking().OrderBy(order).FirstOrDefault(@where);
            }
        }

        public IQueryable<T> Distinct(Expression<Func<T, bool>> @where)
        {
            return this._dbSet.AsNoTracking().Where(@where).Distinct();
        }

        public IQueryable<T> Where(Expression<Func<T, bool>> @where)
        {
            return this._dbSet.Where(@where);
        }

        public IQueryable<T> Where<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, bool isDesc = false)
        {
            if (isDesc)
            {
                return this._dbSet.Where(@where).OrderByDescending(order);
            }
            else
            {
                return this._dbSet.Where(@where).OrderBy(order);
            }
        }

        public IEnumerable<T> Where<TOrder>(Func<T, bool> @where, Func<T, TOrder> order, int pageIndex, int pageSize, out int count, bool isDesc = false)
        {
            count = Count();
            if (isDesc)
            {
                return this._dbSet.Where(@where).OrderByDescending(order).Skip((pageIndex - 1) * pageSize).Take(pageSize);
            }
            else
            {
                return this._dbSet.Where(@where).OrderBy(order).Skip((pageIndex - 1) * pageSize).Take(pageSize);
            }
        }

        public IQueryable<T> Where<TOrder>(Expression<Func<T, bool>> @where, Expression<Func<T, TOrder>> order, int pageIndex, int pageSize, out int count, bool isDesc = false)
        {
            count = Count();
            if (isDesc)
            {
                return this._dbSet.Where(@where).OrderByDescending(order).Skip((pageIndex - 1) * pageSize).Take(pageSize);
            }
            else
            {
                return this._dbSet.Where(@where).OrderBy(order).Skip((pageIndex - 1) * pageSize).Take(pageSize);
            }
        }

        public IQueryable<T> GetAll()
        {
            return this._dbSet.AsNoTracking();
        }

        public IQueryable<T> GetAll<TOrder>(Expression<Func<T, TOrder>> order, bool isDesc = false)
        {
            if (isDesc)
            {
                return this._dbSet.AsNoTracking().OrderByDescending(order);
            }
            else
            {
                return this._dbSet.AsNoTracking().OrderBy(order);
            }
        }

        public T GetById<Ttype>(Ttype id)
        {
            return this._dbSet.Find(id);
        }

        public Ttype Max<Ttype>(Expression<Func<T, Ttype>> column)
        {
            if (this._dbSet.AsNoTracking().Any())
            {
                return this._dbSet.AsNoTracking().Max<T, Ttype>(column);
            }
            return default(Ttype);
        }

        public Ttype Max<Ttype>(Expression<Func<T, Ttype>> column, Expression<Func<T, bool>> @where)
        {
            if (this._dbSet.AsNoTracking().Any(@where))
            {
                return this._dbSet.AsNoTracking().Where(@where).Max<T, Ttype>(column);
            }
            return default(Ttype);
        }

        public Ttype Min<Ttype>(Expression<Func<T, Ttype>> column)
        {
            if (this._dbSet.AsNoTracking().Any())
            {
                return this._dbSet.AsNoTracking().Min<T, Ttype>(column);
            }
            return default(Ttype);
        }

        public Ttype Min<Ttype>(Expression<Func<T, Ttype>> column, Expression<Func<T, bool>> @where)
        {
            if (this._dbSet.AsNoTracking().Any(@where))
            {
                return this._dbSet.AsNoTracking().Where(@where).Min<T, Ttype>(column);
            }
            return default(Ttype);
        }

        public TType Sum<TType>(Expression<Func<T, TType>> selector, Expression<Func<T, bool>> @where) where TType : new()
        {
            object result = 0;

            if (new TType().GetType() == typeof(decimal))
            {
                result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, decimal>>);
            }
            if (new TType().GetType() == typeof(decimal?))
            {
                result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, decimal?>>);
            }
            if (new TType().GetType() == typeof(double))
            {
                result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, double>>);
            }
            if (new TType().GetType() == typeof(double?))
            {
                result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, double?>>);
            }
            if (new TType().GetType() == typeof(float))
            {
                result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, float>>);
            }
            if (new TType().GetType() == typeof(float?))
            {
                result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, float?>>);
            }
            if (new TType().GetType() == typeof(int))
            {
                result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, int>>);
            }
            if (new TType().GetType() == typeof(int?))
            {
                result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, int?>>);
            }
            if (new TType().GetType() == typeof(long))
            {
                result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, long>>);
            }
            if (new TType().GetType() == typeof(long?))
            {
                result = this._dbSet.AsNoTracking().Where(where).Sum(selector as Expression<Func<T, long?>>);
            }
            return (TType)result;
        }

        public void Dispose()
        {
            this._dbContext.Dispose();
        }
    }
}
View Code

這樣倉儲模式就創建好了,接下來想辦法通過DI創建實例,而不是直接在Service層new一個實例,但是Repository是泛型類,通過DI創建需要設置,所有不同model類都要聲明一遍,這里只能使用簡單工廠來處理下。

添加RepositoryFactory類和IRepositoryFactory接口,接口中定義IRepository<T> CreateRepository<T>(IconcardContext mydbcontext) where T : class; 通過實現CreateRepository方法來創建不同數據模型的工作單元。

IRepositoryFactory接口:

using System;
using System.Collections.Generic;
using System.Text;

namespace common.Interface
{
    public interface IRepositoryFactory
    {
        IRepository<T> CreateRepository<T>(IconcardContext mydbcontext) where T : class;
    }
}
View Code

RepositoryFactory類:

using common.Interface;
using System;
using System.Collections.Generic;
using System.Text;

namespace common.Core
{
    public class RepositoryFactory : IRepositoryFactory
    {
        public IRepository<T> CreateRepository<T>(IconcardContext mydbcontext) where T : class
        {
            return new Repository<T>(mydbcontext);
        }
    }
}
View Code

 

 第四步:創建Service層:

 老規矩,先添加新建項目Service和IService,一個是定義Service接口,另一個是它的實現,他們都需要引入Model層和Interface層,Service要引入IService層。

添加BaseService類和IBaseService接口,接口中定義IRepository<T> CreateService<T>() where T : class, new();

IBaseService接口:

using common.Interface;
using System;
using System.Collections.Generic;
using System.Text;

namespace com.Synjones.IService
{
    public interface IBaseService
    {
        IRepository<T> CreateService<T>() where T : class, new();
    }
}
View Code

BaseService類:

using com.Synjones.IService;
using common.Interface;
using System;
using System.Collections.Generic;
using System.Text;

namespace com.Synjones.Service
{
    public class BaseService : IBaseService
    {
        private IRepositoryFactory _repositoryFactory;
        private IconcardContext _mydbcontext;
        public BaseService(IRepositoryFactory repositoryFactory, IconcardContext mydbcontext)
        {
            this._repositoryFactory = repositoryFactory;
            this._mydbcontext = mydbcontext;
        }

        public IRepository<T> CreateService<T>() where T : class, new()
        {
            return _repositoryFactory.CreateRepository<T>(_mydbcontext);
        }
    }
}
View Code

這里說明一下,BaseService類也是泛型類,也不需要通過DI方式創建,Service層中根據每個模塊添加一個Service類,並且繼承BaseService類,DI依賴注入模塊Service中直接獲取到指定模型的倉儲進行操作。

添加User模塊UserService類和IUserService接口,UserService類繼承父類BaseService,生成構造函數。

public UserService(IRepositoryFactory repositoryFactory, IconcardContext mydbcontext) : base(repositoryFactory, mydbcontext)
{
}

下面我們簡單舉例對user表讀取操作的業務層實現,定義接口List<User> GetUsers(),實現GetUsers()方法,讀取所有user表數據。

IUserService接口:

using com.Synjones.Model.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace com.Synjones.IService
{
    public interface IUserService
    {
        List<User> GetUsers();
    }
}
View Code

UserService類:

using com.Synjones.IService;
using com.Synjones.Model.Models;
using common.Interface;
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace com.Synjones.Service
{
    public class UserService : BaseService, IUserService
    {
        public UserService(IRepositoryFactory repositoryFactory, IconcardContext mydbcontext) : base(repositoryFactory, mydbcontext)
        {
        }

        public List<User> GetUsers()
        {
            var service = this.CreateService<User>();
            return service.GetAll().ToList();
        }
    }
}
View Code

 

 

第五步:UI創建並調用Service接口返回數據。

我這里創建了WebApi項目,依賴項中添加引用所有其他項目。

配置數據庫連接字符串,打開appsettings.json,添加

"ConnectionStrings": {
    "SchoolConnection": "server=.;database=ConCard;uid=sa;pwd=123123;"
  }

配置EF服務注冊:

打開Startup.cs,ConfigureServices方法中添加services.AddDbContext指定數據庫連接配置項,通過services.AddScoped添加DI依賴注入配置。

public void ConfigureServices(IServiceCollection services)
{
      services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
      // 配置EF服務注冊
      services.AddDbContext<common.Core.ConCardContext>(options =>
      options.UseSqlServer(Configuration.GetConnectionString("SchoolConnection")));
      services.AddScoped<IconcardContext, common.Core.ConCardContext>();
      services.AddScoped<IRepositoryFactory, RepositoryFactory>();
      services.AddScoped<IUserService, UserService>();
}

修改下ValuesController控制器,添加構造函數和Get方法。

WebApi項目設為啟動項目,運行看結果。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM