• 基于.Net Core3.1 MVC + EF Core的项目(一)框架的初步搭建


    项目暂时分为六大块,结构如图所示

    代码地址是  https://github.com/hudean/VacantCloud-

     

    里面有许多没有完成,不过一些大致的内容都写的差不多了,权限认证依赖注入,支持多种数据库等等。

    Vacant.EntityFrameWorkCore 暂时没有用到

    一、Vacant.Entity 顾名思义主要是存放与数据库交互的实体类,这个项目库里面主要有一个Entitys文件夹存放实体类,还有实体类用到的2个抽象类和两个接口

    1、首先是Entity类代码如下

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Reflection;
      4 using System.Text;
      5 
      6 namespace Vacant.Entitys
      7 {
      8     /// <summary>
      9     /// A shortcut of <see cref="Entity{TPrimaryKey}"/> for most used primary key type (<see cref="int"/>).
     10     /// </summary>
     11     [Serializable]
     12     public abstract class Entity : Entity<long>, IEntity
     13     {
     14 
     15     }
     16 
     17 
     18     /// <summary>
     19     /// Basic implementation of IEntity interface.
     20     /// An entity can inherit this class of directly implement to IEntity interface.
     21     /// </summary>
     22     /// <typeparam name="TPrimaryKey">Type of the primary key of the entity</typeparam>
     23     [Serializable]
     24     public abstract class Entity<TPrimaryKey> : IEntity<TPrimaryKey>
     25     {
     26         /// <summary>
     27         /// Unique identifier for this entity.
     28         /// </summary>
     29         public virtual TPrimaryKey Id { get; set; }
     30 
     31         /// <summary>
     32         /// Checks if this entity is transient (it has not an Id).
     33         /// </summary>
     34         /// <returns>True, if this entity is transient</returns>
     35         public virtual bool IsTransient()
     36         {
     37             if (EqualityComparer<TPrimaryKey>.Default.Equals(Id, default(TPrimaryKey)))
     38             {
     39                 return true;
     40             }
     41 
     42             //Workaround for EF Core since it sets int/long to min value when attaching to dbcontext
     43             if (typeof(TPrimaryKey) == typeof(int))
     44             {
     45                 return Convert.ToInt32(Id) <= 0;
     46             }
     47 
     48             if (typeof(TPrimaryKey) == typeof(long))
     49             {
     50                 return Convert.ToInt64(Id) <= 0;
     51             }
     52 
     53             return false;
     54         }
     55 
     56         /// <inheritdoc/>
     57         public virtual bool EntityEquals(object obj)
     58         {
     59             if (obj == null || !(obj is Entity<TPrimaryKey>))
     60             {
     61                 return false;
     62             }
     63 
     64             //Same instances must be considered as equal
     65             if (ReferenceEquals(this, obj))
     66             {
     67                 return true;
     68             }
     69 
     70             //Transient objects are not considered as equal
     71             var other = (Entity<TPrimaryKey>)obj;
     72             if (IsTransient() && other.IsTransient())
     73             {
     74                 return false;
     75             }
     76 
     77             //Must have a IS-A relation of types or must be same type
     78             var typeOfThis = GetType();
     79             var typeOfOther = other.GetType();
     80             if (!typeOfThis.GetTypeInfo().IsAssignableFrom(typeOfOther) && !typeOfOther.GetTypeInfo().IsAssignableFrom(typeOfThis))
     81             {
     82                 return false;
     83             }
     84 
     85             //if (this is IMayHaveTenant && other is IMayHaveTenant &&
     86             //    this.As<IMayHaveTenant>().TenantId != other.As<IMayHaveTenant>().TenantId)
     87             //{
     88             //    return false;
     89             //}
     90 
     91             //if (this is IMustHaveTenant && other is IMustHaveTenant &&
     92             //    this.As<IMustHaveTenant>().TenantId != other.As<IMustHaveTenant>().TenantId)
     93             //{
     94             //    return false;
     95             //}
     96 
     97             return Id.Equals(other.Id);
     98         }
     99 
    100         public override string ToString()
    101         {
    102             return $"[{GetType().Name} {Id}]";
    103         }
    104     }
    105 }
    View Code

    2、然后是EntityNotFoundException 类代码如下 

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Runtime.Serialization;
     4 using System.Text;
     5 using Vancant.Comman;
     6 
     7 namespace Vacant.Entitys
     8 {
     9     /// <summary>
    10     /// This exception is thrown if an entity excepted to be found but not found.
    11     /// </summary>
    12     [Serializable]
    13     public class EntityNotFoundException : VacantException
    14     {
    15         /// <summary>
    16         /// Type of the entity.
    17         /// </summary>
    18         public Type EntityType { get; set; }
    19 
    20         /// <summary>
    21         /// Id of the Entity.
    22         /// </summary>
    23         public object Id { get; set; }
    24 
    25         /// <summary>
    26         /// Creates a new <see cref="EntityNotFoundException"/> object.
    27         /// </summary>
    28         public EntityNotFoundException()
    29         {
    30 
    31         }
    32 
    33         /// <summary>
    34         /// Creates a new <see cref="EntityNotFoundException"/> object.
    35         /// </summary>
    36         public EntityNotFoundException(SerializationInfo serializationInfo, StreamingContext context)
    37             : base(serializationInfo, context)
    38         {
    39 
    40         }
    41 
    42         /// <summary>
    43         /// Creates a new <see cref="EntityNotFoundException"/> object.
    44         /// </summary>
    45         public EntityNotFoundException(Type entityType, object id)
    46             : this(entityType, id, null)
    47         {
    48 
    49         }
    50 
    51         /// <summary>
    52         /// Creates a new <see cref="EntityNotFoundException"/> object.
    53         /// </summary>
    54         public EntityNotFoundException(Type entityType, object id, Exception innerException)
    55             : base($"There is no such an entity. Entity type: {entityType.FullName}, id: {id}", innerException)
    56         {
    57             EntityType = entityType;
    58             Id = id;
    59         }
    60 
    61         /// <summary>
    62         /// Creates a new <see cref="EntityNotFoundException"/> object.
    63         /// </summary>
    64         /// <param name="message">Exception message</param>
    65         public EntityNotFoundException(string message)
    66             : base(message)
    67         {
    68 
    69         }
    70 
    71         /// <summary>
    72         /// Creates a new <see cref="EntityNotFoundException"/> object.
    73         /// </summary>
    74         /// <param name="message">Exception message</param>
    75         /// <param name="innerException">Inner exception</param>
    76         public EntityNotFoundException(string message, Exception innerException)
    77             : base(message, innerException)
    78         {
    79 
    80         }
    81     }
    82 }
    View Code

    3、然后是接口 IEntityOfTPrimaryKey 代码如下

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 
     5 namespace Vacant.Entitys
     6 {
     7     /// <summary>
     8     /// Defines interface for base entity type. All entities in the system must implement this interface.
     9     /// </summary>
    10     /// <typeparam name="TPrimaryKey">Type of the primary key of the entity</typeparam>
    11     public interface IEntity<TPrimaryKey>
    12     {
    13         /// <summary>
    14         /// Unique identifier for this entity.
    15         /// </summary>
    16         TPrimaryKey Id { get; set; }
    17 
    18         /// <summary>
    19         /// Checks if this entity is transient (not persisted to database and it has not an <see cref="Id"/>).
    20         /// </summary>
    21         /// <returns>True, if this entity is transient</returns>
    22         bool IsTransient();
    23     }
    24 }
    View Code

    4、接口 IEntity 的代码如下

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 
     5 namespace Vacant.Entitys
     6 {
     7     /// <summary>
     8     /// A shortcut of <see cref="IEntity{TPrimaryKey}"/> for most used primary key type (<see cref="long"/>).
     9     /// </summary>
    10     public interface IEntity : IEntity<long>
    11     {
    12 
    13     }
    14 }
    View Code

    二 、现在 实体类库大概完成了,现在开始建一个仓储类库,Vacant.Repositorys里面有三个文件夹分别是DbContexts 、IRepositorys、Repositorys

    1、DbContexts文件夹是放数据库上下文类,添加引用 nuget安装包 Microsoft.EntityFrameworkCore.Design 、Microsoft.EntityFrameworkCore.SqlServer、Microsoft.EntityFrameworkCore.Tools;建一个类名为MSSqlEFDbContext的数据库上下文类

    添加对实体类项目库Entity的引用

    代码如下

     1 using Microsoft.EntityFrameworkCore;
     2 using System;
     3 using System.Collections.Generic;
     4 using System.Text;
     5 
     6 namespace Vacant.Repositorys.DbContexts
     7 {
     8     public class MSSqlEFDbContext : DbContext
     9     {
    10         public MSSqlEFDbContext(DbContextOptions<MSSqlEFDbContext> options) : base(options)
    11         { 
    12         
    13         }
    14 
    15         protected override void OnModelCreating(ModelBuilder modelBuilder)
    16         {
    17             base.OnModelCreating(modelBuilder);
    18         }
    19         //protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    20         //{
    21         //    base.OnConfiguring(optionsBuilder);
    22         //    //连接数据库-一般不用
    23         //    optionsBuilder.UseSqlServer("");
    24         //}
    25     }
    26 }
    View Code

    2、IRepositorys 是放仓存类的泛型接口,这样我们就不需要写三层里的dal层,代码如下

    (1)先建一个接口IRepository 

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 
     5 namespace Vacant.Repositorys.IRepositorys
     6 {
     7     /// <summary>
     8     /// 仓储接口
     9     /// </summary>
    10     public interface IRepository
    11     {
    12 
    13     }
    14 }
    View Code

    (3)再建 接口 IRepositoryOfTEntity 

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 using Vacant.Entitys;
     5 
     6 namespace Vacant.Repositorys.IRepositorys
     7 {
     8     /// <summary>
     9     /// A shortcut of <see cref="IRepository{TEntity,TPrimaryKey}"/> for most used primary key type (<see cref="long"/>).
    10     /// </summary>
    11     /// <typeparam name="TEntity">实体类</typeparam>
    12     public interface IRepository<TEntity> : IRepository<TEntity, long> where TEntity : class, IEntity<long>
    13     {
    14 
    15     }
    16 }
    View Code

    (2)再建接口 IRepositoryOfTEntityAndTPrimaryKey

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Linq.Expressions;
      5 using System.Text;
      6 using System.Threading.Tasks;
      7 using Vacant.Entitys;
      8 
      9 namespace Vacant.Repositorys.IRepositorys
     10 {
     11     /// <summary>
     12     /// This interface is implemented by all repositories to ensure implementation of fixed methods.
     13     /// </summary>
     14     /// <typeparam name="TEntity">Main Entity type this repository works on</typeparam>
     15     /// <typeparam name="TPrimaryKey">Primary key type of the entity</typeparam>
     16     public interface IRepository<TEntity, TPrimaryKey> : IRepository where TEntity : class, IEntity<TPrimaryKey>
     17     {
     18         #region Select/Get/Query
     19 
     20         /// <summary>
     21         /// Used to get a IQueryable that is used to retrieve entities from entire table.
     22         /// </summary>
     23         /// <returns>IQueryable to be used to select entities from database</returns>
     24         IQueryable<TEntity> GetAll();
     25 
     26         /// <summary>
     27         /// Used to get a IQueryable that is used to retrieve entities from entire table.
     28         /// One or more 
     29         /// </summary>
     30         /// <param name="propertySelectors">A list of include expressions.</param>
     31         /// <returns>IQueryable to be used to select entities from database</returns>
     32         IQueryable<TEntity> GetAllIncluding(params Expression<Func<TEntity, object>>[] propertySelectors);
     33 
     34         /// <summary>
     35         /// Used to get all entities.
     36         /// </summary>
     37         /// <returns>List of all entities</returns>
     38         List<TEntity> GetAllList();
     39 
     40         /// <summary>
     41         /// Used to get all entities.
     42         /// </summary>
     43         /// <returns>List of all entities</returns>
     44         Task<List<TEntity>> GetAllListAsync();
     45 
     46         /// <summary>
     47         /// Used to get all entities based on given <paramref name="predicate"/>.
     48         /// </summary>
     49         /// <param name="predicate">A condition to filter entities</param>
     50         /// <returns>List of all entities</returns>
     51         List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate);
     52 
     53         /// <summary>
     54         /// Used to get all entities based on given <paramref name="predicate"/>.
     55         /// </summary>
     56         /// <param name="predicate">A condition to filter entities</param>
     57         /// <returns>List of all entities</returns>
     58         Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate);
     59 
     60         /// <summary>
     61         /// Used to run a query over entire entities.
     62         /// <see cref="UnitOfWorkAttribute"/> attribute is not always necessary (as opposite to <see cref="GetAll"/>)
     63         /// if <paramref name="queryMethod"/> finishes IQueryable with ToList, FirstOrDefault etc..
     64         /// </summary>
     65         /// <typeparam name="T">Type of return value of this method</typeparam>
     66         /// <param name="queryMethod">This method is used to query over entities</param>
     67         /// <returns>Query result</returns>
     68         T Query<T>(Func<IQueryable<TEntity>, T> queryMethod);
     69 
     70         /// <summary>
     71         /// Gets an entity with given primary key.
     72         /// </summary>
     73         /// <param name="id">Primary key of the entity to get</param>
     74         /// <returns>Entity</returns>
     75         TEntity Get(TPrimaryKey id);
     76 
     77         /// <summary>
     78         /// Gets an entity with given primary key.
     79         /// </summary>
     80         /// <param name="id">Primary key of the entity to get</param>
     81         /// <returns>Entity</returns>
     82         Task<TEntity> GetAsync(TPrimaryKey id);
     83 
     84         /// <summary>
     85         /// Gets exactly one entity with given predicate.
     86         /// Throws exception if no entity or more than one entity.
     87         /// </summary>
     88         /// <param name="predicate">Entity</param>
     89         TEntity Single(Expression<Func<TEntity, bool>> predicate);
     90 
     91         /// <summary>
     92         /// Gets exactly one entity with given predicate.
     93         /// Throws exception if no entity or more than one entity.
     94         /// </summary>
     95         /// <param name="predicate">Entity</param>
     96         Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate);
     97 
     98         /// <summary>
     99         /// Gets an entity with given primary key or null if not found.
    100         /// </summary>
    101         /// <param name="id">Primary key of the entity to get</param>
    102         /// <returns>Entity or null</returns>
    103         TEntity FirstOrDefault(TPrimaryKey id);
    104 
    105         /// <summary>
    106         /// Gets an entity with given primary key or null if not found.
    107         /// </summary>
    108         /// <param name="id">Primary key of the entity to get</param>
    109         /// <returns>Entity or null</returns>
    110         Task<TEntity> FirstOrDefaultAsync(TPrimaryKey id);
    111 
    112         /// <summary>
    113         /// Gets an entity with given given predicate or null if not found.
    114         /// </summary>
    115         /// <param name="predicate">Predicate to filter entities</param>
    116         TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate);
    117 
    118         /// <summary>
    119         /// Gets an entity with given given predicate or null if not found.
    120         /// </summary>
    121         /// <param name="predicate">Predicate to filter entities</param>
    122         Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
    123 
    124         /// <summary>
    125         /// Creates an entity with given primary key without database access.
    126         /// </summary>
    127         /// <param name="id">Primary key of the entity to load</param>
    128         /// <returns>Entity</returns>
    129         TEntity Load(TPrimaryKey id);
    130 
    131         #endregion
    132 
    133         #region Insert
    134 
    135         /// <summary>
    136         /// Inserts a new entity.
    137         /// </summary>
    138         /// <param name="entity">Inserted entity</param>
    139         TEntity Insert(TEntity entity);
    140 
    141         /// <summary>
    142         /// Inserts a new entity.
    143         /// </summary>
    144         /// <param name="entity">Inserted entity</param>
    145         Task<TEntity> InsertAsync(TEntity entity);
    146 
    147         /// <summary>
    148         /// Inserts a new entity and gets it's Id.
    149         /// It may require to save current unit of work
    150         /// to be able to retrieve id.
    151         /// </summary>
    152         /// <param name="entity">Entity</param>
    153         /// <returns>Id of the entity</returns>
    154         TPrimaryKey InsertAndGetId(TEntity entity);
    155 
    156         /// <summary>
    157         /// Inserts a new entity and gets it's Id.
    158         /// It may require to save current unit of work
    159         /// to be able to retrieve id.
    160         /// </summary>
    161         /// <param name="entity">Entity</param>
    162         /// <returns>Id of the entity</returns>
    163         Task<TPrimaryKey> InsertAndGetIdAsync(TEntity entity);
    164 
    165         /// <summary>
    166         /// Inserts or updates given entity depending on Id's value.
    167         /// </summary>
    168         /// <param name="entity">Entity</param>
    169         TEntity InsertOrUpdate(TEntity entity);
    170 
    171         /// <summary>
    172         /// Inserts or updates given entity depending on Id's value.
    173         /// </summary>
    174         /// <param name="entity">Entity</param>
    175         Task<TEntity> InsertOrUpdateAsync(TEntity entity);
    176 
    177         /// <summary>
    178         /// Inserts or updates given entity depending on Id's value.
    179         /// Also returns Id of the entity.
    180         /// It may require to save current unit of work
    181         /// to be able to retrieve id.
    182         /// </summary>
    183         /// <param name="entity">Entity</param>
    184         /// <returns>Id of the entity</returns>
    185         TPrimaryKey InsertOrUpdateAndGetId(TEntity entity);
    186 
    187         /// <summary>
    188         /// Inserts or updates given entity depending on Id's value.
    189         /// Also returns Id of the entity.
    190         /// It may require to save current unit of work
    191         /// to be able to retrieve id.
    192         /// </summary>
    193         /// <param name="entity">Entity</param>
    194         /// <returns>Id of the entity</returns>
    195         Task<TPrimaryKey> InsertOrUpdateAndGetIdAsync(TEntity entity);
    196 
    197         #endregion
    198 
    199         #region Update
    200 
    201         /// <summary>
    202         /// Updates an existing entity.
    203         /// </summary>
    204         /// <param name="entity">Entity</param>
    205         TEntity Update(TEntity entity);
    206 
    207         /// <summary>
    208         /// Updates an existing entity. 
    209         /// </summary>
    210         /// <param name="entity">Entity</param>
    211         Task<TEntity> UpdateAsync(TEntity entity);
    212 
    213         /// <summary>
    214         /// Updates an existing entity.
    215         /// </summary>
    216         /// <param name="id">Id of the entity</param>
    217         /// <param name="updateAction">Action that can be used to change values of the entity</param>
    218         /// <returns>Updated entity</returns>
    219         TEntity Update(TPrimaryKey id, Action<TEntity> updateAction);
    220 
    221         /// <summary>
    222         /// Updates an existing entity.
    223         /// </summary>
    224         /// <param name="id">Id of the entity</param>
    225         /// <param name="updateAction">Action that can be used to change values of the entity</param>
    226         /// <returns>Updated entity</returns>
    227         Task<TEntity> UpdateAsync(TPrimaryKey id, Func<TEntity, Task> updateAction);
    228 
    229         #endregion
    230 
    231         #region Delete
    232 
    233         /// <summary>
    234         /// Deletes an entity.
    235         /// </summary>
    236         /// <param name="entity">Entity to be deleted</param>
    237         void Delete(TEntity entity);
    238 
    239         /// <summary>
    240         /// Deletes an entity.
    241         /// </summary>
    242         /// <param name="entity">Entity to be deleted</param>
    243         Task DeleteAsync(TEntity entity);
    244 
    245         /// <summary>
    246         /// Deletes an entity by primary key.
    247         /// </summary>
    248         /// <param name="id">Primary key of the entity</param>
    249         void Delete(TPrimaryKey id);
    250 
    251         /// <summary>
    252         /// Deletes an entity by primary key.
    253         /// </summary>
    254         /// <param name="id">Primary key of the entity</param>
    255         Task DeleteAsync(TPrimaryKey id);
    256 
    257         /// <summary>
    258         /// Deletes many entities by function.
    259         /// Notice that: All entities fits to given predicate are retrieved and deleted.
    260         /// This may cause major performance problems if there are too many entities with
    261         /// given predicate.
    262         /// </summary>
    263         /// <param name="predicate">A condition to filter entities</param>
    264         void Delete(Expression<Func<TEntity, bool>> predicate);
    265 
    266         /// <summary>
    267         /// Deletes many entities by function.
    268         /// Notice that: All entities fits to given predicate are retrieved and deleted.
    269         /// This may cause major performance problems if there are too many entities with
    270         /// given predicate.
    271         /// </summary>
    272         /// <param name="predicate">A condition to filter entities</param>
    273         Task DeleteAsync(Expression<Func<TEntity, bool>> predicate);
    274 
    275         #endregion
    276 
    277         #region Aggregates
    278 
    279         /// <summary>
    280         /// Gets count of all entities in this repository.
    281         /// </summary>
    282         /// <returns>Count of entities</returns>
    283         int Count();
    284 
    285         /// <summary>
    286         /// Gets count of all entities in this repository.
    287         /// </summary>
    288         /// <returns>Count of entities</returns>
    289         Task<int> CountAsync();
    290 
    291         /// <summary>
    292         /// Gets count of all entities in this repository based on given <paramref name="predicate"/>.
    293         /// </summary>
    294         /// <param name="predicate">A method to filter count</param>
    295         /// <returns>Count of entities</returns>
    296         int Count(Expression<Func<TEntity, bool>> predicate);
    297 
    298         /// <summary>
    299         /// Gets count of all entities in this repository based on given <paramref name="predicate"/>.
    300         /// </summary>
    301         /// <param name="predicate">A method to filter count</param>
    302         /// <returns>Count of entities</returns>
    303         Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate);
    304 
    305         /// <summary>
    306         /// Gets count of all entities in this repository (use if expected return value is greather than <see cref="int.MaxValue"/>.
    307         /// </summary>
    308         /// <returns>Count of entities</returns>
    309         long LongCount();
    310 
    311         /// <summary>
    312         /// Gets count of all entities in this repository (use if expected return value is greather than <see cref="int.MaxValue"/>.
    313         /// </summary>
    314         /// <returns>Count of entities</returns>
    315         Task<long> LongCountAsync();
    316 
    317         /// <summary>
    318         /// Gets count of all entities in this repository based on given <paramref name="predicate"/>
    319         /// (use this overload if expected return value is greather than <see cref="int.MaxValue"/>).
    320         /// </summary>
    321         /// <param name="predicate">A method to filter count</param>
    322         /// <returns>Count of entities</returns>
    323         long LongCount(Expression<Func<TEntity, bool>> predicate);
    324 
    325         /// <summary>
    326         /// Gets count of all entities in this repository based on given <paramref name="predicate"/>
    327         /// (use this overload if expected return value is greather than <see cref="int.MaxValue"/>).
    328         /// </summary>
    329         /// <param name="predicate">A method to filter count</param>
    330         /// <returns>Count of entities</returns>
    331         Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate);
    332 
    333         #endregion
    334     }
    335 }
    View Code

    3、Repositorys 是放仓存类的泛型类的

    (1)建一个 RepositoryBase 抽象父类实现IRepository接口,代码如下

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Linq.Expressions;
      5 using System.Text;
      6 using System.Threading.Tasks;
      7 using Vacant.Entitys;
      8 using Vacant.Repositorys.IRepositorys;
      9 
     10 namespace Vacant.Repositorys.Repositorys
     11 {
     12     /// <summary>
     13     /// 抽象仓储类
     14     /// </summary>
     15     /// <typeparam name="TEntity">实体类</typeparam>
     16     /// <typeparam name="TPrimaryKey">主键</typeparam>
     17     public abstract class RepositoryBase<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey> where TEntity : class, IEntity<TPrimaryKey>
     18     {
     19         public abstract IQueryable<TEntity> GetAll();
     20 
     21         public virtual IQueryable<TEntity> GetAllIncluding(params Expression<Func<TEntity, object>>[] propertySelectors)
     22         {
     23             return GetAll();
     24         }
     25 
     26         public virtual List<TEntity> GetAllList()
     27         {
     28             return GetAll().ToList();
     29         }
     30 
     31         public virtual Task<List<TEntity>> GetAllListAsync()
     32         {
     33             return Task.FromResult(GetAllList());
     34         }
     35 
     36         public virtual List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate)
     37         {
     38             return GetAll().Where(predicate).ToList();
     39         }
     40 
     41         public virtual Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate)
     42         {
     43             return Task.FromResult(GetAllList(predicate));
     44         }
     45 
     46         public virtual T Query<T>(Func<IQueryable<TEntity>, T> queryMethod)
     47         {
     48             return queryMethod(GetAll());
     49         }
     50 
     51         public virtual TEntity Get(TPrimaryKey id)
     52         {
     53             var entity = FirstOrDefault(id);
     54             if (entity == null)
     55             {
     56                 throw new EntityNotFoundException(typeof(TEntity), id);
     57             }
     58 
     59             return entity;
     60         }
     61 
     62         public virtual async Task<TEntity> GetAsync(TPrimaryKey id)
     63         {
     64             var entity = await FirstOrDefaultAsync(id);
     65             if (entity == null)
     66             {
     67                 throw new EntityNotFoundException(typeof(TEntity), id);
     68             }
     69 
     70             return entity;
     71         }
     72 
     73         public virtual TEntity Single(Expression<Func<TEntity, bool>> predicate)
     74         {
     75             return GetAll().Single(predicate);
     76         }
     77 
     78         public virtual Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate)
     79         {
     80             return Task.FromResult(Single(predicate));
     81         }
     82 
     83         public virtual TEntity FirstOrDefault(TPrimaryKey id)
     84         {
     85             return GetAll().FirstOrDefault(CreateEqualityExpressionForId(id));
     86         }
     87 
     88         public virtual Task<TEntity> FirstOrDefaultAsync(TPrimaryKey id)
     89         {
     90             return Task.FromResult(FirstOrDefault(id));
     91         }
     92 
     93         public virtual TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate)
     94         {
     95             return GetAll().FirstOrDefault(predicate);
     96         }
     97 
     98         public virtual Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate)
     99         {
    100             return Task.FromResult(FirstOrDefault(predicate));
    101         }
    102 
    103         public virtual TEntity Load(TPrimaryKey id)
    104         {
    105             return Get(id);
    106         }
    107 
    108         public abstract TEntity Insert(TEntity entity);
    109 
    110         public virtual Task<TEntity> InsertAsync(TEntity entity)
    111         {
    112             return Task.FromResult(Insert(entity));
    113         }
    114 
    115         public virtual TPrimaryKey InsertAndGetId(TEntity entity)
    116         {
    117             return Insert(entity).Id;
    118         }
    119 
    120         public virtual async Task<TPrimaryKey> InsertAndGetIdAsync(TEntity entity)
    121         {
    122             var insertedEntity = await InsertAsync(entity);
    123             return insertedEntity.Id;
    124         }
    125 
    126         public virtual TEntity InsertOrUpdate(TEntity entity)
    127         {
    128             return entity.IsTransient()
    129                 ? Insert(entity)
    130                 : Update(entity);
    131         }
    132 
    133         public virtual async Task<TEntity> InsertOrUpdateAsync(TEntity entity)
    134         {
    135             return entity.IsTransient()
    136                 ? await InsertAsync(entity)
    137                 : await UpdateAsync(entity);
    138         }
    139 
    140         public virtual TPrimaryKey InsertOrUpdateAndGetId(TEntity entity)
    141         {
    142             return InsertOrUpdate(entity).Id;
    143         }
    144 
    145         public virtual async Task<TPrimaryKey> InsertOrUpdateAndGetIdAsync(TEntity entity)
    146         {
    147             var insertedEntity = await InsertOrUpdateAsync(entity);
    148             return insertedEntity.Id;
    149         }
    150 
    151         public abstract TEntity Update(TEntity entity);
    152 
    153         public virtual Task<TEntity> UpdateAsync(TEntity entity)
    154         {
    155             return Task.FromResult(Update(entity));
    156         }
    157 
    158         public virtual TEntity Update(TPrimaryKey id, Action<TEntity> updateAction)
    159         {
    160             var entity = Get(id);
    161             updateAction(entity);
    162             return entity;
    163         }
    164 
    165         public virtual async Task<TEntity> UpdateAsync(TPrimaryKey id, Func<TEntity, Task> updateAction)
    166         {
    167             var entity = await GetAsync(id);
    168             await updateAction(entity);
    169             return entity;
    170         }
    171 
    172         public abstract void Delete(TEntity entity);
    173 
    174         public virtual Task DeleteAsync(TEntity entity)
    175         {
    176             Delete(entity);
    177             return Task.CompletedTask;
    178         }
    179 
    180         public abstract void Delete(TPrimaryKey id);
    181 
    182         public virtual Task DeleteAsync(TPrimaryKey id)
    183         {
    184             Delete(id);
    185             return Task.CompletedTask;
    186         }
    187 
    188         public virtual void Delete(Expression<Func<TEntity, bool>> predicate)
    189         {
    190             foreach (var entity in GetAllList(predicate))
    191             {
    192                 Delete(entity);
    193             }
    194         }
    195 
    196         public virtual async Task DeleteAsync(Expression<Func<TEntity, bool>> predicate)
    197         {
    198             var entities = await GetAllListAsync(predicate);
    199 
    200             foreach (var entity in entities)
    201             {
    202                 await DeleteAsync(entity);
    203             }
    204         }
    205 
    206         public virtual int Count()
    207         {
    208             return GetAll().Count();
    209         }
    210 
    211         public virtual Task<int> CountAsync()
    212         {
    213             return Task.FromResult(Count());
    214         }
    215 
    216         public virtual int Count(Expression<Func<TEntity, bool>> predicate)
    217         {
    218             return GetAll().Count(predicate);
    219         }
    220 
    221         public virtual Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate)
    222         {
    223             return Task.FromResult(Count(predicate));
    224         }
    225 
    226         public virtual long LongCount()
    227         {
    228             return GetAll().LongCount();
    229         }
    230 
    231         public virtual Task<long> LongCountAsync()
    232         {
    233             return Task.FromResult(LongCount());
    234         }
    235 
    236         public virtual long LongCount(Expression<Func<TEntity, bool>> predicate)
    237         {
    238             return GetAll().LongCount(predicate);
    239         }
    240 
    241         public virtual Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate)
    242         {
    243             return Task.FromResult(LongCount(predicate));
    244         }
    245 
    246         protected virtual Expression<Func<TEntity, bool>> CreateEqualityExpressionForId(TPrimaryKey id)
    247         {
    248             var lambdaParam = Expression.Parameter(typeof(TEntity));
    249 
    250             var leftExpression = Expression.PropertyOrField(lambdaParam, "Id");
    251 
    252             var idValue = Convert.ChangeType(id, typeof(TPrimaryKey));
    253 
    254             Expression<Func<object>> closure = () => idValue;
    255             var rightExpression = Expression.Convert(closure.Body, leftExpression.Type);
    256 
    257             var lambdaBody = Expression.Equal(leftExpression, rightExpression);
    258 
    259             return Expression.Lambda<Func<TEntity, bool>>(lambdaBody, lambdaParam);
    260         }
    261     }
    262 }
    View Code

    (2)建一个 子类EFRepository 继承RepositoryBase 这个类,代码如下

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using Vacant.Entitys;
     6 using Vacant.Repositorys.DbContexts;
     7 using Vacant.Repositorys.IRepositorys;
     8 
     9 namespace Vacant.Repositorys.Repositorys
    10 {
    11     /// <summary>
    12     /// 使用Ef的sqlserver版本
    13     /// </summary>
    14     /// <typeparam name="TEntity"></typeparam>
    15     public class EFRepository<TEntity> : EFRepository<TEntity, long>, IRepository<TEntity> where TEntity : class, IEntity<long>
    16     {
    17         public EFRepository(MSSqlEFDbContext dbContext) : base(dbContext)
    18         {
    19 
    20         }
    21     }
    22 
    23 
    24     public class EFRepository<TEntity, TPrimaryKey> : RepositoryBase<TEntity, TPrimaryKey> where TEntity : class, IEntity<TPrimaryKey>
    25     {
    26         public readonly MSSqlEFDbContext _dbContext;
    27 
    28         public EFRepository(MSSqlEFDbContext dbContext)
    29         {
    30             _dbContext = dbContext;
    31         }
    32         public override void Delete(TEntity entity)
    33         {
    34             _dbContext.Set<TEntity>().Remove(entity);
    35             _dbContext.SaveChanges();
    36         }
    37 
    38         public override void Delete(TPrimaryKey id)
    39         {
    40             var entity = _dbContext.Set<TEntity>().SingleOrDefault(t => t.Id.Equals(id));
    41             Delete(entity);
    42 
    43         }
    44 
    45         public override IQueryable<TEntity> GetAll()
    46         {
    47             return _dbContext.Set<TEntity>().AsQueryable();
    48         }
    49 
    50         public override TEntity Insert(TEntity entity)
    51         {
    52             _dbContext.Set<TEntity>().Add(entity);
    53             _dbContext.SaveChanges();
    54             return entity;
    55         }
    56 
    57         public override TEntity Update(TEntity entity)
    58         {
    59             _dbContext.Set<TEntity>().Update(entity);
    60             _dbContext.SaveChanges();
    61             return entity;
    62         }
    63     }
    64     
    65 }
    View Code

    三、现在泛型仓储库大致完成了,我们开始建一个Vacant.Services类库、里面有两个文件夹,分别是IServices 和Services ,添加对仓库项目库和实体项目库的引用

    四、Vancant.Comman是项目公共帮助类库 ,先建3个类分别是 HttpHelper、VacantException、ValidateCode,上面的类库都要添加对此项目的引用

       (1)HttpHelper是发送http请求的帮助类的代码如下

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Net.Http;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 
      7 namespace Vancant.Comman
      8 {
      9     /// <summary>
     10     /// http请求帮助类
     11     /// </summary>
     12     public class HttpHelper
     13     {
     14         /// <summary>
     15         /// 发起POST同步请求
     16         /// 
     17         /// </summary>
     18         /// <param name="url"></param>
     19         /// <param name="postData"></param>
     20         /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
     21         /// <param name="headers">填充消息头</param>        
     22         /// <returns></returns>
     23         public static string HttpPost(string url, string postData = null, string contentType = null, int timeOut = 30, Dictionary<string, string> headers = null)
     24         {
     25             postData = postData ?? "";
     26             using (HttpClient client = new HttpClient())
     27             {
     28                 if (headers != null)
     29                 {
     30                     foreach (var header in headers)
     31                         client.DefaultRequestHeaders.Add(header.Key, header.Value);
     32                 }
     33                 using (HttpContent httpContent = new StringContent(postData, Encoding.UTF8))
     34                 {
     35                     if (contentType != null)
     36                         httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);
     37 
     38                     HttpResponseMessage response = client.PostAsync(url, httpContent).Result;
     39                     return response.Content.ReadAsStringAsync().Result;
     40                 }
     41             }
     42         }
     43 
     44 
     45         /// <summary>
     46         /// 发起POST异步请求
     47         /// </summary>
     48         /// <param name="url"></param>
     49         /// <param name="postData"></param>
     50         /// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
     51         /// <param name="headers">填充消息头</param>        
     52         /// <returns></returns>
     53         public static async Task<string> HttpPostAsync(string url, string postData = null, string contentType = null, int timeOut = 30, Dictionary<string, string> headers = null)
     54         {
     55             postData = postData ?? "";
     56             using (HttpClient client = new HttpClient())
     57             {
     58                 client.Timeout = new TimeSpan(0, 0, timeOut);
     59                 if (headers != null)
     60                 {
     61                     foreach (var header in headers)
     62                         client.DefaultRequestHeaders.Add(header.Key, header.Value);
     63                 }
     64                 using (HttpContent httpContent = new StringContent(postData, Encoding.UTF8))
     65                 {
     66                     if (contentType != null)
     67                         httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);
     68 
     69                     HttpResponseMessage response = await client.PostAsync(url, httpContent);
     70                     return await response.Content.ReadAsStringAsync();
     71                 }
     72             }
     73         }
     74 
     75         /// <summary>
     76         /// 发起GET同步请求
     77         /// </summary>
     78         /// <param name="url"></param>
     79         /// <param name="headers"></param>
     80         /// <param name="contentType"></param>
     81         /// <returns></returns>
     82         public static string HttpGet(string url, Dictionary<string, string> headers = null)
     83         {
     84             using (HttpClient client = new HttpClient())
     85             {
     86                 if (headers != null)
     87                 {
     88                     foreach (var header in headers)
     89                         client.DefaultRequestHeaders.Add(header.Key, header.Value);
     90                 }
     91                 HttpResponseMessage response = client.GetAsync(url).Result;
     92                 return response.Content.ReadAsStringAsync().Result;
     93             }
     94         }
     95 
     96         /// <summary>
     97         /// 发起GET异步请求
     98         /// </summary>
     99         /// <param name="url"></param>
    100         /// <param name="headers"></param>
    101         /// <param name="contentType"></param>
    102         /// <returns></returns>
    103         public static async Task<string> HttpGetAsync(string url, Dictionary<string, string> headers = null)
    104         {
    105             using (HttpClient client = new HttpClient())
    106             {
    107                 if (headers != null)
    108                 {
    109                     foreach (var header in headers)
    110                         client.DefaultRequestHeaders.Add(header.Key, header.Value);
    111                 }
    112                 HttpResponseMessage response = await client.GetAsync(url);
    113                 return await response.Content.ReadAsStringAsync();
    114             }
    115         }
    116     }
    117 }
    View Code

     (2)VacantException是错误异常

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Runtime.Serialization;
     4 using System.Text;
     5 
     6 namespace Vancant.Comman
     7 {
     8     /// <summary>
     9     /// Base exception type for those are thrown by Abp system for Abp specific exceptions.
    10     /// </summary>
    11     [Serializable]
    12     public class VacantException : Exception
    13     {
    14         /// <summary>
    15         /// Creates a new <see cref="AbpException"/> object.
    16         /// </summary>
    17         public VacantException()
    18         {
    19 
    20         }
    21 
    22         /// <summary>
    23         /// Creates a new <see cref="AbpException"/> object.
    24         /// </summary>
    25         public VacantException(SerializationInfo serializationInfo, StreamingContext context)
    26             : base(serializationInfo, context)
    27         {
    28 
    29         }
    30 
    31         /// <summary>
    32         /// Creates a new <see cref="AbpException"/> object.
    33         /// </summary>
    34         /// <param name="message">Exception message</param>
    35         public VacantException(string message)
    36             : base(message)
    37         {
    38 
    39         }
    40 
    41         /// <summary>
    42         /// Creates a new <see cref="AbpException"/> object.
    43         /// </summary>
    44         /// <param name="message">Exception message</param>
    45         /// <param name="innerException">Inner exception</param>
    46         public VacantException(string message, Exception innerException)
    47             : base(message, innerException)
    48         {
    49 
    50         }
    51     }
    52 }
    View Code

      (3)ValidateCode是生成随机的验证码 ,注意 一定添加nuget安装包 System.Drawing.Common

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 using System.Drawing;
     5 using System.Drawing.Imaging;
     6 using System.IO;
     7 
     8 namespace Vancant.Comman
     9 {
    10     /// <summary>
    11     /// 验证码
    12     /// </summary>
    13     public class ValidateCode
    14     {
    15         public byte[] GetVerifyCode(out string code)
    16         {
    17             code = string.Empty;
    18             int codeW = 80;
    19             int codeH = 30;
    20             int fontSize = 16;
    21             string chkCode = string.Empty;
    22             Random rnd = new Random();
    23             //颜色列表,用于验证码、噪线、噪点
    24             Color[] color = { Color.Black, Color.Red, Color.Blue, Color.Green, Color.Orange, Color.Brown, Color.Brown, Color.DarkBlue };
    25             //字体列表,用于验证码
    26             string[] font = { "Times New Roman" };
    27             //验证码的字符集,去掉了一些容易混淆的字符
    28             char[] character = { '2', '3', '4', '5', '6', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'h', 'k', 'm', 'n', 'r', 'x', 'y', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'W', 'X', 'Y' };
    29             //生成验证码字符串
    30             for (int i = 0; i < 4; i++)
    31             {
    32                 chkCode += character[rnd.Next(character.Length)];
    33             }
    34             code = chkCode;
    35 
    36             //创建画布
    37             Bitmap bmp = new Bitmap(codeW, codeH);
    38             Graphics g = Graphics.FromImage(bmp);
    39             g.Clear(Color.White);
    40             //画噪线
    41             for (int i = 0; i < 1; i++)
    42             {
    43                 int x1 = rnd.Next(codeW);
    44                 int y1 = rnd.Next(codeH);
    45                 int x2 = rnd.Next(codeW);
    46                 int y2 = rnd.Next(codeH);
    47                 Color clr = color[rnd.Next(color.Length)];
    48                 g.DrawLine(new Pen(clr), x1, y1, x2, y2);
    49             }
    50             //画验证码字符串
    51             for (int i = 0; i < chkCode.Length; i++)
    52             {
    53                 string fnt = font[rnd.Next(font.Length)];
    54                 Font ft = new Font(fnt, fontSize);
    55                 Color clr = color[rnd.Next(color.Length)];
    56                 g.DrawString(chkCode[i].ToString(), ft, new SolidBrush(clr), (float)i * 18, (float)0);
    57             }
    58             //将验证码图片写入内存流,并将其以 "image/Png" 格式输出
    59             MemoryStream ms = new MemoryStream();
    60             try
    61             {
    62                 bmp.Save(ms, ImageFormat.Png);
    63                 return ms.ToArray();
    64             }
    65             catch (Exception)
    66             {
    67                 return null;
    68             }
    69             finally
    70             {
    71                 g.Dispose();
    72                 bmp.Dispose();
    73             }
    74         }
    75 
    76     }
    77 }
    View Code

    五、现在开始建.net core mvc 3.1 版本的web应用程序 Vacant.Web添加对上面四个项目的引用

    statupp类进行配置,里面代码如下,

    services.AddScoped(typeof(IRepository<,>), typeof(EFRepository<,>));
    services.AddScoped(typeof(IRepository<>), typeof(EFRepository<>));  是泛型注入

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Reflection;
      5 using System.Threading.Tasks;
      6 using Microsoft.AspNetCore.Builder;
      7 using Microsoft.AspNetCore.Hosting;
      8 using Microsoft.AspNetCore.HttpsPolicy;
      9 using Microsoft.EntityFrameworkCore;
     10 using Microsoft.Extensions.Configuration;
     11 using Microsoft.Extensions.DependencyInjection;
     12 using Microsoft.Extensions.Hosting;
     13 using Vacant.Repositorys.DbContexts;
     14 using Vacant.Repositorys.IRepositorys;
     15 using Vacant.Repositorys.Repositorys;
     16 using Vacant.Services.IServices;
     17 
     18 namespace Vacant.Web
     19 {
     20     public class Startup
     21     {
     22         public Startup(IConfiguration configuration)
     23         {
     24             Configuration = configuration;
     25         }
     26 
     27         public IConfiguration Configuration { get; }
     28 
     29         // This method gets called by the runtime. Use this method to add services to the container.
     30         public void ConfigureServices(IServiceCollection services)
     31         {
     32             services.AddControllersWithViews();
     33             //注册服务连接数据库
     34             services.AddDbContext<MSSqlEFDbContext>(options =>
     35             {
     36                 options.UseSqlServer(Configuration.GetConnectionString("Default"));//获取配置的连接字符串
     37                 //options.UseMySql(Configuration.GetConnectionString("Default"));
     38                 //options.UseSqlite(Configuration.GetConnectionString("Default"));
     39                 //options.UseNpgsql(Configuration.GetConnectionString("Default"));
     40             });
     41 
     42             #region 依赖注入仓储
     43 
     44             //重点仓储和服务注入方式要一样
     45             //依赖注入仓储  
     46             services.AddScoped(typeof(IRepository<,>), typeof(EFRepository<,>));
     47             services.AddScoped(typeof(IRepository<>), typeof(EFRepository<>));
     48 
     49             //services.AddScoped<IUserService,UserService>();
     50             //services.AddScoped<IRoleService, RoleService>();
     51             #endregion
     52 
     53             #region 批量注入
     54             //加载程序集MyApplication
     55             var serviceAsm = Assembly.Load(new AssemblyName("Vacant.Services"));
     56             foreach (Type serviceType in serviceAsm.GetTypes().Where(t => typeof(IBaseService).IsAssignableFrom(t) && !t.GetTypeInfo().IsAbstract))
     57             {
     58                 var interfaceTypes = serviceType.GetInterfaces();
     59                 foreach (var interfaceType in interfaceTypes)
     60                 {
     61                     services.AddScoped(interfaceType, serviceType);
     62                 }
     63             }
     64 
     65             #endregion
     66             services.AddSession();
     67             services.AddMvc(options =>
     68             {
     69                 options.Filters.Add<Filter.MyErrorExceptionFilter>();
     70             });
     71         }
     72 
     73         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
     74         public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
     75         {
     76             if (env.IsDevelopment())
     77             {
     78                 app.UseDeveloperExceptionPage();
     79             }
     80             else
     81             {
     82                 app.UseExceptionHandler("/Home/Error");
     83                 // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
     84                 app.UseHsts();
     85             }
     86             app.UseHttpsRedirection();
     87             app.UseStaticFiles();
     88 
     89             app.UseRouting();
     90 
     91             app.UseAuthorization();
     92 
     93             app.UseEndpoints(endpoints =>
     94             {
     95                 endpoints.MapControllerRoute(
     96                     name: "default",
     97                     pattern: "{controller=Home}/{action=Index}/{id?}");
     98             });
     99         }
    100     }
    101 }
    View Code
  • 相关阅读:
    实现Oracle的字符串分割(split)[摘录]
    批处理加密[转摘]
    .NET Framework 3.5 SP1安装时下载文件问题及精简方法[转载]
    Oracle 管道化表函数(Pipelined Table)[转载]
    FCKeditor只读与编辑状态切换的不完全解决方案[原创]
    C# Web开发中弹出对话框的函数[转载]
    广发信用卡提现手续费及利息计算器VB源码[原创]
    提升个人网站流量的工具集合(真实IP流量)[转载]
    12.26 3日沙盘Top20分析
    12.29 股票量能沙盘分析软件更新
  • 原文地址:https://www.cnblogs.com/hudean/p/13392066.html
Copyright © 2020-2023  润新知