基於.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

 


免責聲明!

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



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