1-UI,登陆界面布局
PS:使用的是metronic 框架,没有用过的可以自行百度。
1.1 metronic 放在wwwroot文件夹下面
1.2 metronic 中的 open sans 使用的是 谷歌的DNS,所以我们需要自己下载本地资源(使用nuget管理器下载,也可以用nuget控制台)。
1.3 创建Account控制器和视图 ,由于现在不支持在controller中直接右击生成视图文件,因此我们需要自己在Views文件下创建Account文件夹和Login.cshtml文件。
1.3.1 在Account 中创建布局页面Layout.cshtml
1 <!DOCTYPE html> 2 <!--[if IE 8]> <html lang="en" class="ie8 no-js"> <![endif]--> 3 <!--[if IE 9]> <html lang="en" class="ie9 no-js"> <![endif]--> 4 <!--[if !IE]><!--> 5 <html lang="en"> 6 <!--<![endif]--> 7 <!-- BEGIN HEAD --> 8 <head> 9 <meta charset="utf-8" /> 10 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 11 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 12 <meta content="" name="description" /> 13 <meta content="" name="author" /> 14 <title>@ViewData["Title"] - NET Core Demo</title> 15 <environment names="Development"> 16 <link rel="stylesheet" href="~/css/font-open-sans.css" /> 17 <link href="~/metronic/assets/global/plugins/font-awesome/css/font-awesome.css" rel="stylesheet" type="text/css" /> 18 <link href="~/metronic/assets/global/plugins/bootstrap/css/bootstrap.css" rel="stylesheet" type="text/css" /> 19 <link href="~/metronic/assets/global/css/components.css" rel="stylesheet" id="style_components" type="text/css" /> 20 <link href="~/metronic/assets/pages/css/login.css" rel="stylesheet" type="text/css" /> 21 </environment> 22 <environment names="Staging,Production"> 23 <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Open+Sans:400,300,600,700&subset=all" 24 asp-fallback-href="~/css/font-open-sans.min.css" 25 asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" /> 26 <link href="~/metronic/assets/global/plugins/font-awesome/css/font-awesome.css" rel="stylesheet" type="text/css" /> 27 <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.6/css/bootstrap.min.css" 28 asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css" 29 asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" /> 30 <link href="~/metronic/assets/global/css/components.min.css" rel="stylesheet" id="style_components" type="text/css" /> 31 <link href="~/metronic/assets/pages/css/login.min.css" rel="stylesheet" type="text/css" /> 32 </environment> 33 @RenderSection("css", required: false) 34 @Html.ApplicationInsightsJavaScript(TelemetryConfiguration) 35 </head> 36 <body class="login"> 37 <div class="logo"> 38 <a href="index.html"> 39 <img src="~/metronic/assets/pages/img/logo-big.png" alt="" /> 40 </a> 41 </div> 42 <div class="content"> 43 @RenderBody() 44 </div> 45 <div class="copyright">2014 © Metronic. Admin Dashboard Template.</div> 46 <!--[if lt IE 9]> 47 <script src="~/metronic/assets/global/plugins/respond.min.js"></script> 48 <script src="~/metronic/assets/global/plugins/excanvas.min.js"></script> 49 <![endif]--> 50 <script src="~/metronic/assets/global/plugins/jquery.min.js" type="text/javascript"></script> 51 <script src="~/metronic/assets/global/plugins/bootstrap/js/bootstrap.min.js" type="text/javascript"></script> 52 @*<script src="~/metronic/assets/global/plugins/js.cookie.min.js" type="text/javascript"></script>*@ 53 <script src="~/metronic/assets/global/plugins/jquery-validation/js/jquery.validate.min.js" type="text/javascript"></script> 54 @*<script src="~/metronic/assets/global/plugins/jquery-validation/js/additional-methods.min.js" type="text/javascript"></script>*@ 55 <script src="~/metronic/assets/global/scripts/app.min.js" type="text/javascript"></script> 56 57 @RenderSection("scripts", required: false) 58 </body> 59 </html>
1.3.2 login登陆页面
1 <form class="login-form" asp-action="Login" asp-controller="Account" method="post"> 2 @Html.AntiForgeryToken() 3 <h3 class="form-title font-green">登录</h3> 4 <div class="alert alert-danger display-hide"> 5 <button class="close" data-close="alert"></button> 6 <span> 请输入用户名或密码. </span> 7 </div> 8 @if (ViewBag.IsInvalid) 9 { 10 <div class="alert alert-danger"> 11 <button class="close" data-close="alert"></button> 12 <span> @ViewBag.ErrorMsg. </span> 13 </div> 14 } 15 <div class="form-group"> 16 <!--ie8, ie9 does not support html5 placeholder, so we just show field title for that--> 17 <label class="control-label visible-ie8 visible-ie9">用户名</label> 18 <input class="form-control form-control-solid placeholder-no-fix" type="text" autocomplete="off" placeholder="用户名" name="username" /> 19 </div> 20 <div class="form-group"> 21 <label class="control-label visible-ie8 visible-ie9">密码</label> 22 <input class="form-control form-control-solid placeholder-no-fix" type="password" autocomplete="off" placeholder="密码" name="password" /> 23 </div> 24 <div class="form-actions"> 25 <button type="submit" class="btn green uppercase">登录</button> 26 <label class="rememberme check"> 27 <input type="checkbox" name="remember" value="1" />记住密码 28 </label> 29 <a asp-area="" asp-controller="Account" asp-action="ForgetPassword" id="forget-password" class="forget-password">忘记密码?</a> 30 </div> 31 <input hidden id="returnUrl" name="returnUrl" value="@ViewBag.ReturnUrl" /> 32 </form> 33 @section scripts{ 34 <environment names="Development"> 35 <script src="~/js/account/login.js" type="text/javascript"></script> 36 </environment> 37 <environment names="Staging,Production"> 38 <script src="~/js/account/login.min.js" type="text/javascript"></script> 39 </environment> 40 }
1.3.3 配置文件压缩机制bundleconfig.json (压缩文件只有当你发布系统的时候才会生成,DEBUG的时候不会生成)。
2- 登录代码实现,依赖注册
2.1 GR.Core中创建IRepository通用仓储接口(该代码来自ABP的实现,我自己有修改)。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Linq.Expressions; 5 using System.Threading.Tasks; 6 using GR.Core.Domain; 7 8 namespace GR.Core.Data 9 { 10 /// <summary> 11 /// Repository 12 /// </summary> 13 public partial interface IRepository<TEntity> :IRepository<TEntity, int> where TEntity : BaseEntity 14 { 15 16 } 17 18 /// <summary> 19 /// This interface is implemented by all repositories to ensure implementation of fixed methods. 20 /// </summary> 21 /// <remarks> 22 /// 参考ABP实现 https://github.com/aspnetboilerplate 23 /// </remarks> 24 /// <typeparam name="TEntity">Main Entity type this repository works on</typeparam> 25 /// <typeparam name="TPrimaryKey">Primary key type of the entity</typeparam> 26 public interface IRepository<TEntity, TPrimaryKey> where TEntity : BaseEntity 27 { 28 #region Select/Get/Query 29 30 /// <summary> 31 /// Used to get a IQueryable that is used to retrieve entities from entire table. 32 /// <see cref="UnitOfWorkAttribute"/> attribute must be used to be able to call this method since this method 33 /// returns IQueryable and it requires open database connection to use it. 34 /// </summary> 35 /// <returns>IQueryable to be used to select entities from database</returns> 36 IQueryable<TEntity> GetAll(); 37 38 /// <summary> 39 /// Used to get all entities. 40 /// </summary> 41 /// <returns>List of all entities</returns> 42 List<TEntity> GetAllList(); 43 44 /// <summary> 45 /// Used to get all entities. 46 /// </summary> 47 /// <returns>List of all entities</returns> 48 Task<List<TEntity>> GetAllListAsync(); 49 50 /// <summary> 51 /// Used to get all entities based on given <paramref name="predicate"/>. 52 /// </summary> 53 /// <param name="predicate">A condition to filter entities</param> 54 /// <returns>List of all entities</returns> 55 List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate); 56 57 /// <summary> 58 /// Used to get all entities based on given <paramref name="predicate"/>. 59 /// </summary> 60 /// <param name="predicate">A condition to filter entities</param> 61 /// <returns>List of all entities</returns> 62 Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate); 63 64 /// <summary> 65 /// Used to run a query over entire entities. 66 /// <see cref="UnitOfWorkAttribute"/> attribute is not always necessary (as opposite to <see cref="GetAll"/>) 67 /// if <paramref name="queryMethod"/> finishes IQueryable with ToList, FirstOrDefault etc.. 68 /// </summary> 69 /// <typeparam name="T">Type of return value of this method</typeparam> 70 /// <param name="queryMethod">This method is used to query over entities</param> 71 /// <returns>Query result</returns> 72 T Query<T>(Func<IQueryable<TEntity>, T> queryMethod); 73 74 /// <summary> 75 /// Gets an entity with given primary key. 76 /// </summary> 77 /// <param name="id">Primary key of the entity to get</param> 78 /// <returns>Entity</returns> 79 TEntity Get(TPrimaryKey id); 80 81 /// <summary> 82 /// Gets an entity with given primary key. 83 /// </summary> 84 /// <param name="id">Primary key of the entity to get</param> 85 /// <returns>Entity</returns> 86 Task<TEntity> GetAsync(TPrimaryKey id); 87 88 /// <summary> 89 /// Gets exactly one entity with given predicate. 90 /// Throws exception if no entity or more than one entity. 91 /// </summary> 92 /// <param name="predicate">Entity</param> 93 TEntity Single(Expression<Func<TEntity, bool>> predicate); 94 95 /// <summary> 96 /// Gets exactly one entity with given predicate. 97 /// Throws exception if no entity or more than one entity. 98 /// </summary> 99 /// <param name="predicate">Entity</param> 100 Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate); 101 102 /// <summary> 103 /// Gets an entity with given primary key or null if not found. 104 /// </summary> 105 /// <param name="id">Primary key of the entity to get</param> 106 /// <returns>Entity or null</returns> 107 TEntity FirstOrDefault(TPrimaryKey id); 108 109 /// <summary> 110 /// Gets an entity with given primary key or null if not found. 111 /// </summary> 112 /// <param name="id">Primary key of the entity to get</param> 113 /// <returns>Entity or null</returns> 114 Task<TEntity> FirstOrDefaultAsync(TPrimaryKey id); 115 116 /// <summary> 117 /// Gets an entity with given given predicate or null if not found. 118 /// </summary> 119 /// <param name="predicate">Predicate to filter entities</param> 120 TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate); 121 122 /// <summary> 123 /// Gets an entity with given given predicate or null if not found. 124 /// </summary> 125 /// <param name="predicate">Predicate to filter entities</param> 126 Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate); 127 128 /// <summary> 129 /// Creates an entity with given primary key without database access. 130 /// </summary> 131 /// <param name="id">Primary key of the entity to load</param> 132 /// <returns>Entity</returns> 133 TEntity Load(TPrimaryKey id); 134 135 #endregion 136 137 138 /// <summary> 139 /// Inserts a new entity. 140 /// </summary> 141 /// <param name="entity">Inserted entity</param> 142 int Insert(TEntity entity, bool IsCommit = true); 143 144 /// <summary> 145 /// Inserts a new entity. 146 /// </summary> 147 /// <param name="entity">Inserted entity</param> 148 Task<int> InsertAsync(TEntity entity, bool IsCommit = true); 149 150 /// <summary> 151 /// Inserts or updates given entity depending on Id's value. 152 /// </summary> 153 /// <param name="entity">Entity</param> 154 int InsertOrUpdate(TEntity entity, bool IsCommit = true); 155 156 /// <summary> 157 /// Inserts or updates given entity depending on Id's value. 158 /// </summary> 159 /// <param name="entity">Entity</param> 160 Task<int> InsertOrUpdateAsync(TEntity entity, bool IsCommit = true); 161 162 /// <summary> 163 /// Updates an existing entity. 164 /// </summary> 165 /// <param name="entity">Entity</param> 166 int Update(TEntity entity, bool IsCommit = true); 167 168 /// <summary> 169 /// Updates an existing entity. 170 /// </summary> 171 /// <param name="entity">Entity</param> 172 Task<int> UpdateAsync(TEntity entity, bool IsCommit = true); 173 174 175 /// <summary> 176 /// Deletes an entity. 177 /// </summary> 178 /// <param name="entity">Entity to be deleted</param> 179 int Delete(TEntity entity, bool IsCommit = true); 180 181 /// <summary> 182 /// Deletes an entity. 183 /// </summary> 184 /// <param name="entity">Entity to be deleted</param> 185 Task DeleteAsync(TEntity entity, bool IsCommit = true); 186 187 /// <summary> 188 /// Deletes an entity by primary key. 189 /// </summary> 190 /// <param name="id">Primary key of the entity</param> 191 int Delete(TPrimaryKey id, bool IsCommit = true); 192 193 /// <summary> 194 /// Deletes an entity by primary key. 195 /// </summary> 196 /// <param name="id">Primary key of the entity</param> 197 Task DeleteAsync(TPrimaryKey id, bool IsCommit = true); 198 199 /// <summary> 200 /// Deletes many entities by function. 201 /// Notice that: All entities fits to given predicate are retrieved and deleted. 202 /// This may cause major performance problems if there are too many entities with 203 /// given predicate. 204 /// </summary> 205 /// <param name="predicate">A condition to filter entities</param> 206 void Delete(Expression<Func<TEntity, bool>> predicate, bool IsCommit = true); 207 208 /// <summary> 209 /// Deletes many entities by function. 210 /// Notice that: All entities fits to given predicate are retrieved and deleted. 211 /// This may cause major performance problems if there are too many entities with 212 /// given predicate. 213 /// </summary> 214 /// <param name="predicate">A condition to filter entities</param> 215 Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool IsCommit = true); 216 217 218 #region Aggregates 219 220 /// <summary> 221 /// Gets count of all entities in this repository. 222 /// </summary> 223 /// <returns>Count of entities</returns> 224 int Count(); 225 226 /// <summary> 227 /// Gets count of all entities in this repository. 228 /// </summary> 229 /// <returns>Count of entities</returns> 230 Task<int> CountAsync(); 231 232 /// <summary> 233 /// Gets count of all entities in this repository based on given <paramref name="predicate"/>. 234 /// </summary> 235 /// <param name="predicate">A method to filter count</param> 236 /// <returns>Count of entities</returns> 237 int Count(Expression<Func<TEntity, bool>> predicate); 238 239 /// <summary> 240 /// Gets count of all entities in this repository based on given <paramref name="predicate"/>. 241 /// </summary> 242 /// <param name="predicate">A method to filter count</param> 243 /// <returns>Count of entities</returns> 244 Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate); 245 246 /// <summary> 247 /// Gets count of all entities in this repository (use if expected return value is greather than <see cref="int.MaxValue"/>. 248 /// </summary> 249 /// <returns>Count of entities</returns> 250 long LongCount(); 251 252 /// <summary> 253 /// Gets count of all entities in this repository (use if expected return value is greather than <see cref="int.MaxValue"/>. 254 /// </summary> 255 /// <returns>Count of entities</returns> 256 Task<long> LongCountAsync(); 257 258 /// <summary> 259 /// Gets count of all entities in this repository based on given <paramref name="predicate"/> 260 /// (use this overload if expected return value is greather than <see cref="int.MaxValue"/>). 261 /// </summary> 262 /// <param name="predicate">A method to filter count</param> 263 /// <returns>Count of entities</returns> 264 long LongCount(Expression<Func<TEntity, bool>> predicate); 265 266 /// <summary> 267 /// Gets count of all entities in this repository based on given <paramref name="predicate"/> 268 /// (use this overload if expected return value is greather than <see cref="int.MaxValue"/>). 269 /// </summary> 270 /// <param name="predicate">A method to filter count</param> 271 /// <returns>Count of entities</returns> 272 Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate); 273 274 #endregion 275 } 276 }
2.2 GR.Data中创建EFRepository通用仓储实现(该代码来自ABP的实现,我自己有修改)。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Linq.Expressions; 5 using System.Threading.Tasks; 6 using GR.Core.Data; 7 using GR.Core.Domain; 8 using Microsoft.EntityFrameworkCore; 9 10 namespace GR.Data.Repository 11 { 12 /// <summary> 13 /// 14 /// </summary> 15 /// <typeparam name="TEntity"></typeparam> 16 public class EfRepository<TEntity> : EfRepositoryBase<GRDbContext, TEntity, int>, IRepository<TEntity> where TEntity : BaseEntity 17 { 18 public EfRepository(GRDbContext dbContext) : base(dbContext) 19 { } 20 } 21 22 /// <summary> 23 /// 通用仓储基类 24 /// </summary> 25 /// <remarks> 26 /// 参考了 ABP 的 仓储基类 27 /// https://github.com/aspnetboilerplate 28 /// </remarks> 29 /// <typeparam name="TDbContext"></typeparam> 30 /// <typeparam name="TEntity"></typeparam> 31 /// <typeparam name="TPrimaryKey"></typeparam> 32 public abstract class EfRepositoryBase<TDbContext, TEntity, TPrimaryKey> 33 where TDbContext : DbContext 34 where TEntity : BaseEntity 35 { 36 private readonly TDbContext _dbContext; 37 38 public EfRepositoryBase(TDbContext dbContext) 39 { 40 _dbContext = dbContext; 41 } 42 43 /// <summary> 44 /// Gets DbSet for given entity. 45 /// </summary> 46 public virtual DbSet<TEntity> Table 47 { 48 get 49 { 50 return _dbContext.Set<TEntity>(); 51 } 52 } 53 54 /// <summary> 55 /// Gets EF DbContext object. 56 /// </summary> 57 public virtual TDbContext DbContext 58 { 59 get { return _dbContext; } 60 } 61 62 public IQueryable<TEntity> GetAll() 63 { 64 return Table; 65 } 66 67 public TEntity FirstOrDefault(TPrimaryKey id) 68 { 69 return GetAll().FirstOrDefault(CreateEqualityExpressionForId(id)); 70 } 71 72 public List<TEntity> GetAllList() 73 { 74 return Table.ToList(); 75 } 76 77 public List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate) 78 { 79 return Table.Where(predicate).ToList(); 80 } 81 82 public async Task<List<TEntity>> GetAllListAsync() 83 { 84 return await GetAll().ToListAsync(); 85 } 86 87 public async Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate) 88 { 89 return await GetAll().Where(predicate).ToListAsync(); 90 } 91 92 public T Query<T>(Func<IQueryable<TEntity>, T> queryMethod) 93 { 94 return queryMethod(GetAll()); 95 } 96 97 public TEntity Get(TPrimaryKey id) 98 { 99 var entity = FirstOrDefault(id); 100 if (entity == null) 101 { 102 throw new ArgumentNullException("There is no such an entity with given primary key. Entity type: " + typeof(TEntity).FullName + ", primary key: " + id); 103 } 104 return entity; 105 } 106 107 public async Task<TEntity> GetAsync(TPrimaryKey id) 108 { 109 var entity = await FirstOrDefaultAsync(id); 110 if (entity == null) 111 { 112 throw new ArgumentNullException("There is no such an entity with given primary key. Entity type: " + typeof(TEntity).FullName + ", primary key: " + id); 113 } 114 115 return entity; 116 } 117 118 public TEntity Single(Expression<Func<TEntity, bool>> predicate) 119 { 120 return GetAll().Single(predicate); 121 } 122 123 public async Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate) 124 { 125 return await GetAll().SingleAsync(predicate); 126 } 127 128 public async Task<TEntity> FirstOrDefaultAsync(TPrimaryKey id) 129 { 130 return await GetAll().FirstOrDefaultAsync(CreateEqualityExpressionForId(id)); 131 } 132 133 public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate) 134 { 135 return await GetAll().FirstOrDefaultAsync(predicate); 136 } 137 138 public int Insert(TEntity entity, bool IsCommit = true) 139 { 140 Table.Add(entity); 141 return IsCommit ? _dbContext.SaveChanges() : -1; 142 } 143 144 public Task<int> InsertAsync(TEntity entity, bool IsCommit = true) 145 { 146 Table.Add(entity); 147 return IsCommit ? Task.FromResult(_dbContext.SaveChanges()) : Task.FromResult(-1); 148 } 149 150 public int Update(TEntity entity, bool IsCommit = true) 151 { 152 AttachIfNot(entity); 153 _dbContext.Entry(entity).State = EntityState.Modified; 154 return IsCommit ? _dbContext.SaveChanges() : -1; 155 } 156 157 public Task<int> UpdateAsync(TEntity entity, bool IsCommit = true) 158 { 159 AttachIfNot(entity); 160 _dbContext.Entry(entity).State = EntityState.Modified; 161 return IsCommit ? Task.FromResult(_dbContext.SaveChanges()) : Task.FromResult(-1); 162 } 163 164 165 public int InsertOrUpdate(TEntity entity, bool IsCommit = true) 166 { 167 return entity.IsTransient() ? Insert(entity, IsCommit) : Update(entity, IsCommit); 168 } 169 170 public async Task<int> InsertOrUpdateAsync(TEntity entity, bool IsCommit = true) 171 { 172 return entity.IsTransient() ? await InsertAsync(entity, IsCommit) : await UpdateAsync(entity, IsCommit); 173 } 174 175 public int Delete(TEntity entity, bool IsCommit = true) 176 { 177 AttachIfNot(entity); 178 Table.Remove(entity); 179 return IsCommit ? _dbContext.SaveChanges() : -1; 180 } 181 182 public int Delete(TPrimaryKey id, bool IsCommit = true) 183 { 184 var entity = FirstOrDefault(id); 185 if (entity == null) 186 { 187 return 0; 188 } 189 return Delete(entity, IsCommit); 190 } 191 192 public Task DeleteAsync(TEntity entity, bool IsCommit = true) 193 { 194 return Task.FromResult(Delete(entity, IsCommit)); 195 } 196 197 public Task DeleteAsync(TPrimaryKey id, bool IsCommit = true) 198 { 199 return Task.FromResult(Delete(id, IsCommit)); 200 } 201 202 public void Delete(Expression<Func<TEntity, bool>> predicate, bool IsCommit = true) 203 { 204 var entities = GetAll().Where(predicate).ToList(); 205 entities.ForEach(entity => 206 { 207 Delete(entity, IsCommit); 208 }); 209 } 210 211 212 public Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool IsCommit = true) 213 { 214 Delete(predicate, IsCommit); 215 return Task.FromResult(1); 216 } 217 public async Task<int> CountAsync() 218 { 219 return await GetAll().CountAsync(); 220 } 221 222 public async Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate) 223 { 224 return await GetAll().Where(predicate).CountAsync(); 225 } 226 227 public async Task<long> LongCountAsync() 228 { 229 return await GetAll().LongCountAsync(); 230 } 231 232 public async Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate) 233 { 234 return await GetAll().Where(predicate).LongCountAsync(); 235 } 236 237 protected static Expression<Func<TEntity, bool>> CreateEqualityExpressionForId(TPrimaryKey id) 238 { 239 var lambdaParam = Expression.Parameter(typeof(TEntity)); 240 241 var lambdaBody = Expression.Equal( 242 Expression.PropertyOrField(lambdaParam, "Id"), 243 Expression.Constant(id, typeof(TPrimaryKey)) 244 ); 245 246 return Expression.Lambda<Func<TEntity, bool>>(lambdaBody, lambdaParam); 247 } 248 249 protected void AttachIfNot(TEntity entity) 250 { 251 //if (!Table.Local.Contains(entity)) 252 //{ 253 // Table.Attach(entity); 254 //} 255 Table.Attach(entity); 256 } 257 258 public int Commit() 259 { 260 return _dbContext.SaveChanges(); 261 } 262 263 public async Task<int> CommitAsync() 264 { 265 return await _dbContext.SaveChangesAsync(); 266 } 267 268 public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate) 269 { 270 return GetAll().FirstOrDefault(predicate); 271 } 272 273 public TEntity Load(TPrimaryKey id) 274 { 275 return Get(id); 276 } 277 278 public int Count() 279 { 280 return GetAll().Count(); 281 } 282 283 public int Count(Expression<Func<TEntity, bool>> predicate) 284 { 285 return GetAll().Where(predicate).Count(); 286 } 287 288 public long LongCount() 289 { 290 return GetAll().LongCount(); 291 } 292 293 public long LongCount(Expression<Func<TEntity, bool>> predicate) 294 { 295 return GetAll().Where(predicate).LongCount(); 296 } 297 298 } 299 }
2.3 GR.Data中创建DependencyRegister依赖注册类(从Startup中分解出来)
之后只要是在Data中添加的类需要依赖注入,都是在该类中添加
1 using System; 2 using GR.Core.Data; 3 using GR.Data.Repository; 4 using Microsoft.EntityFrameworkCore; 5 using Microsoft.Extensions.DependencyInjection; 6 7 namespace GR.Data 8 { 9 public class DependencyRegister 10 { 11 public static void ConfigureServices(IServiceCollection services) 12 { 13 services.AddDbContext<GRDbContext>(ServiceLifetime.Singleton); 14 services.AddScoped(typeof(IRepository<>), typeof(EfRepository<>)); 15 } 16 } 17 }
2.3 GR.Servies中创建AccountService类,创建DTO实体模型,以及DependencyRegister依赖注册类
2.4 在gr.web中的startup添加依赖注册
3-结束
这样子登陆功能就完成了,其他的数据验证和.NET FRAMEWORK的一样