# 创建一个简单的.net core 框架程序

创建一个简单的.net core 框架程序

​ 最近项目比较紧张,抽空学习了一下框架是怎么搭建的,学习的比较零碎,学习的地方比较多,遇到的问题也是比较多的,自己学习是比较乏味枯燥的过程,学习还是断断续续的,遇到的难点踩坑比较多,过程是比较痛苦的。现在.net core跨平台已经适用于生产环境中去了,我也是在慢慢的研究了一下,并没有去系统的学习,用到什么就学习什么这种状态,记录一下;
第一步先创建一个.net Core MVC项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GzqFw58f-1619617941963)(屏幕截图 2021-04-11 194826.png)]

第二步创建一些类库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ov5SyOwU-1619617941966)(屏幕截图 2021-04-11 195955.png)]

Application:是应用服务层
Core:是实体模型层
EFWork:是连接上下文和仓储服务层
现在互相引用一下,关系如下

Core
EasyFramework
EFWork
Application
Core
Application
EFWork
EFWork
Core

先在Core类库中创建一个实体类和一个抽象类
抽象类里面添加一些常用的字段
抽象类

 public abstract class EntityBase
 {
     public EntityBase()
     {
         CreateTime = DateTime.Now;
     }
     [Key]
     public int Id { get; set; }
     public DateTime CreateTime { get; set; }
 }

一个用户实体并且继承EntityBase


 public class Users : EntityBase
 {

     [StringLength(20)]
     public string UserName { get; set; }
     [StringLength(20, MinimumLength = 6)]
     public string Password { get; set; }
 }

然后在EFWork中引用EntityFrameworkCore和Microsoft.EntityFrameworkCore.SqlServer因为我使用的数据库是Microsoft SQL Server 就用EF这套来连接操作数据库(其他数据库也有异曲同工之妙)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UpFiCoOU-1619617941969)(屏幕截图 2021-04-11 202343.png)]

操作完毕开始连接数据库和手写仓储方法
在EFWork中创建一个连接数据库的上下文

 public class WebDbContext:DbContext
 {
     public DbSet<Users> users { get; set; }
     public WebDbContext(DbContextOptions<WebDbContext> options) : base(options)
     { 
     
     }
 }

然后创建Repository类和IRepository接口类

   public class Repository<TEntity, TDbContext> : IRepository<TEntity> where TEntity : class
  {
     private readonly WebDbContext dbContext;
     public Repository(WebDbContext _dbContext)
     {
         dbContext = _dbContext;
     }
     /// <summary>
     /// 新增数据
     /// </summary>
     /// <param name="entity">实体</param>
     /// <returns></returns>
     public TEntity Add(TEntity entity)
     {
         var result = dbContext.Set<TEntity>().Add(entity).Entity;
         dbContext.SaveChanges();
         return result;
     }
     /// <summary>
     /// 异步新增数据
     /// </summary>
     /// <param name="entity">实体</param>
     /// <returns></returns>
     public async Task<TEntity> AddAsync(TEntity entity)
     {
         var result = (await dbContext.Set<TEntity>().AddAsync(entity)).Entity;
         await dbContext.SaveChangesAsync();
         return result;
     }
     /// <summary>
     /// 删除数据
     /// </summary>
     /// <param name="entity">实体</param>
     public int Delete(TEntity entity)
     {
         dbContext.Set<TEntity>().Remove(entity);
         dbContext.Entry(entity).State = Microsoft.EntityFrameworkCore.EntityState.Deleted;
         return dbContext.SaveChanges();

     }
     /// <summary>
     /// 异步删除数据
     /// </summary>
     /// <param name="entity">实体</param>
     /// <returns></returns>
     public async Task<int> DeleteAsync(TEntity entity)
     {
         return await Task.FromResult(Delete(entity));
     }
     /// <summary>
     /// 更新数据
     /// </summary>
     /// <param name="entity">实体</param>
     /// <returns></returns>
     public TEntity Update(TEntity entity)
     {
         var result = dbContext.Set<TEntity>().Update(entity).Entity;
         dbContext.Entry(entity).State = Microsoft.EntityFrameworkCore.EntityState.Detached;
         dbContext.SaveChanges();
         return result;
     }
     /// <summary>
     /// 异步更新数据
     /// </summary>
     /// <param name="entity">实体</param>
     /// <returns></returns>
     public async Task<TEntity> UpdateAsync(TEntity entity)
     {
         var result = await Task.FromResult(Update(entity));
         return result;
     }
     /// <summary>
     /// 通过拉姆达表达式查找数据
     /// </summary>
     /// <param name="predicate">表达式</param>
     /// <returns></returns>
     public IEnumerable<TEntity> GetAll(Func<TEntity, bool> predicate)
     {
         return dbContext.Set<TEntity>().Where(predicate);
     }
     /// <summary>
     /// 异步通过拉姆达表达式查找数据
     /// </summary>
     /// <param name="predicate">表达式</param>
     /// <returns></returns>
     public async Task<IEnumerable<TEntity>> GetAllList(Func<TEntity, bool> predicate)
     {
         return await Task.FromResult(GetAll(predicate));
     }
     /// <summary>
     /// 通过分页查询数据
     /// </summary>
     /// <param name="predicateOrder">正序排列条件</param>
     /// <param name="predicate">查询条件</param>
     /// <param name="Count">返回条数</param>
     /// <param name="PageIndex">页码</param>
     /// <param name="PageSize">页的大小</param>
     /// <returns></returns>
     public IEnumerable<TEntity> PageRequestResult(Func<TEntity, bool> predicateOrder, Func<TEntity, bool> predicate, out int Count, int PageIndex = 1, int PageSize = 10)
     {
         var result = dbContext.Set<TEntity>().Where(predicate).OrderBy(predicateOrder).Take((PageIndex - 1) * PageSize).Skip(PageSize);
         Count = result.Count();
         return result;
     }
     /// <summary>
     /// 其他方法扩展
     /// </summary>
     /// <returns></returns>
     public DbSet<TEntity> OtherExtend()
     {
         var result = dbContext.Set<TEntity>();
         return result;
     }

 }
  public interface IRepository<TEntity> where TEntity : class
 {
     /// <summary>
     /// 新增数据
     /// </summary>
     /// <param name="entity">实体</param>
     /// <returns></returns>
     TEntity Add(TEntity entity);
     /// <summary>
     /// 异步新增数据
     /// </summary>
     /// <param name="entity">实体</param>
     /// <returns></returns>
     Task<TEntity> AddAsync(TEntity entity);
     /// <summary>
     /// 删除数据
     /// </summary>
     /// <param name="entity">实体</param>
     int Delete(TEntity entity);
     /// <summary>
     /// 异步删除数据
     /// </summary>
     /// <param name="entity">实体</param>
     /// <returns></returns>
     Task<int> DeleteAsync(TEntity entity);
     /// <summary>
     /// 更新数据
     /// </summary>
     /// <param name="entity">实体</param>
     /// <returns></returns>
     TEntity Update(TEntity entity);
     /// <summary>
     /// 异步更新数据
     /// </summary>
     /// <param name="entity">实体</param>
     /// <returns></returns>
     Task<TEntity> UpdateAsync(TEntity entity);
     /// <summary>
     /// 通过拉姆达表达式查找数据
     /// </summary>
     /// <param name="predicate">表达式</param>
     /// <returns></returns>
     IEnumerable<TEntity> GetAll(Func<TEntity, bool> predicate);
     /// <summary>
     /// 异步通过拉姆达表达式查找数据
     /// </summary>
     /// <param name="predicate">表达式</param>
     /// <returns></returns>
     Task<IEnumerable<TEntity>> GetAllList(Func<TEntity, bool> predicate);
     /// <summary>
     /// 通过分页查询数据
     /// </summary>
     /// <param name="predicateOrder">正序排列条件</param>
     /// <param name="predicate">查询条件</param>
     /// <param name="Count">返回条数</param>
     /// <param name="PageIndex">页码</param>
     /// <param name="PageSize">页的大小</param>
     /// <returns></returns>
     IEnumerable<TEntity> PageRequestResult(Func<TEntity, bool> predicateOrder, Func<TEntity, bool> predicate, out int Count, int PageIndex = 1, int PageSize = 10);
     /// <summary>
     /// 其他方法扩展
     /// </summary>
     /// <returns></returns>
     DbSet<TEntity> OtherExtend();

仓储内的方法只写了一些,也可以自由扩展一下
然后迁移数据库,先在appsettings.json中配置数据库

{
"ConnectionStrings": {
 "DefaultConnection": "Server=.;Database=EFWorkDB;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
 "LogLevel": {
   "Default": "Information",
   "Microsoft": "Warning",
   "Microsoft.Hosting.Lifetime": "Information"
 }
},
"AllowedHosts": "*"
}

在Startup中配置service

  public void ConfigureServices(IServiceCollection services)
     {
         //注册DbConfig,连接数据库
         services.AddDbContext<WebDbContext>(options =>
             options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
         //添加数据库异常筛选器 需要下载Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore,并且引用
         services.AddDatabaseDeveloperPageExceptionFilter();
         services.AddControllersWithViews();
     }

找到命令控制台选择默认项目为EFWork项目,然后安装数据迁移命令库Install-Package Microsoft.EntityFrameworkCore.Tools

在mvc项目中安装包Install-Package Microsoft.EntityFrameworkCore.Design

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uZ2AnnMu-1619617941972)(屏幕截图 2021-04-14 165838.png)]

Add-Migration 命令会通知迁移框架使用当前 DB 架构检查当前 users 模型,并创建必要的代码,将 DB 迁移到新模型。

Update-Database更新数据库
迁移成功后可以查看数据库是否正确,迁移过程中可能会缺少一些相应的库,在nuget上下载即可;
然后我们在Application项目中添加我们的服务,添加一个ApplicationModule类添加一些相关的方法

 public class AsyncCrudAppService<TEntity> : IAsyncCrudAppService<TEntity> where TEntity : class
    {
        private readonly IRepository<TEntity> repository;
        public AsyncCrudAppService(IRepository<TEntity> _repository)
        {
            repository = _repository;
        }
        /// <summary>
        /// 新增数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        public TEntity Add(TEntity entity)
        {
            var result = repository.Add(entity);
            return result;
        }
        /// <summary>
        /// 异步新增数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        public async Task<TEntity> AddAsync(TEntity entity)
        {
            var result = await repository.AddAsync(entity);
            return result;
        }
        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="entity">实体</param>
        public int Delete(TEntity entity)
        {

            return repository.Delete(entity);

        }
        /// <summary>
        /// 异步删除数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        public async Task<int> DeleteAsync(TEntity entity)
        {
            return await repository.DeleteAsync(entity);
        }
        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        public TEntity Update(TEntity entity)
        {
            var result = repository.Update(entity);
            return result;
        }
        /// <summary>
        /// 异步更新数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        public async Task<TEntity> UpdateAsync(TEntity entity)
        {
            var result = await repository.UpdateAsync(entity);
            return result;
        }
        /// <summary>
        /// 通过拉姆达表达式查找数据
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <returns></returns>
        public IEnumerable<TEntity> GetAll(Func<TEntity, bool> predicate)
        {
            return repository.GetAll(predicate);
        }
        /// <summary>
        /// 异步通过拉姆达表达式查找数据
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <returns></returns>
        public async Task<IEnumerable<TEntity>> GetAllList(Func<TEntity, bool> predicate)
        {
            return await repository.GetAllList(predicate);
        }
        /// <summary>
        /// 通过分页查询数据
        /// </summary>
        /// <param name="predicateOrder">正序排列条件</param>
        /// <param name="predicate">查询条件</param>
        /// <param name="Count">返回条数</param>
        /// <param name="PageIndex">页码</param>
        /// <param name="PageSize">页的大小</param>
        /// <returns></returns>
        public IEnumerable<TEntity> PageRequestResult(Func<TEntity, bool> predicateOrder, Func<TEntity, bool> predicate, out int Count, int PageIndex = 1, int PageSize = 10)
        {
            var result = repository.PageRequestResult(predicateOrder,predicate,out Count,PageIndex,PageSize);           
            return result;
        }

    }
    public interface IAsyncCrudAppService<TEntity> where TEntity : class
    {
        /// <summary>
        /// 新增数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        TEntity Add(TEntity entity);
        /// <summary>
        /// 异步新增数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        Task<TEntity> AddAsync(TEntity entity);
        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="entity">实体</param>
        int Delete(TEntity entity);
        /// <summary>
        /// 异步删除数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        Task<int> DeleteAsync(TEntity entity);
        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        TEntity Update(TEntity entity);
        /// <summary>
        /// 异步更新数据
        /// </summary>
        /// <param name="entity">实体</param>
        /// <returns></returns>
        Task<TEntity> UpdateAsync(TEntity entity);
        /// <summary>
        /// 通过拉姆达表达式查找数据
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <returns></returns>
        IEnumerable<TEntity> GetAll(Func<TEntity, bool> predicate);
        /// <summary>
        /// 异步通过拉姆达表达式查找数据
        /// </summary>
        /// <param name="predicate">表达式</param>
        /// <returns></returns>
        Task<IEnumerable<TEntity>> GetAllList(Func<TEntity, bool> predicate);
        /// <summary>
        /// 通过分页查询数据
        /// </summary>
        /// <param name="predicateOrder">正序排列条件</param>
        /// <param name="predicate">查询条件</param>
        /// <param name="Count">返回条数</param>
        /// <param name="PageIndex">页码</param>
        /// <param name="PageSize">页的大小</param>
        /// <returns></returns>
        IEnumerable<TEntity> PageRequestResult(Func<TEntity, bool> predicateOrder, Func<TEntity, bool> predicate, out int Count, int PageIndex = 1, int PageSize = 10);

    }

这个类中的相应代码,主要时为了减少代码的重复操作
我们在Sevcies和IService中继承这两个类就行了

                          Service
     public class UserService : AsyncCrudAppService<Users>, IUserService
     {
        private readonly IRepository<Users> repository;
        public UserService(IRepository<Users> _repository) : base(_repository)
        {           
        }
     }
                           IService
    public interface IUserService : IAsyncCrudAppService<Users>
    {
    }

然后我们需要在Startup中注册相关项

 services.AddScoped<IRepository<Users>, Repository<Users>>();
 services.AddScoped<IAsyncCrudAppService<Users>, AsyncCrudAppService<Users>>();
 services.AddScoped<IUserService, UserService>();

在HomeController中添加一些功能
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hvgKVYF1-1619617941973)(屏幕截图 2021-04-14 191048.png)]

写了获取数据和添加数据功能,其他功能可以自由扩展,就不一一列出了
基本的操作已经做完了
接下来就是登录的了

先创建一个AccountController控制器,然后在Startup中配置注册权限过滤

            //身份验证注册
            app.UseAuthentication();

再全局注册权限验证机制和登录时的Cookie信息

//在 Startup.ConfigureServices 方法中,创建具有和方法的身份验证中间件服务 AddAuthentication AddCookie 
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
           {
               //没有登陆时,将会将请求重定向到这个相对路径
               options.LoginPath = new PathString("/Account/Login");
               //登录后cookie的名称
               options.Cookie.Name = "My_Cookie";
               //没有访问权限时,将会将请求重定向到这个相对路径
               options.AccessDeniedPath = new PathString("/Home/Error");
           });
            //全局加入身份验证
            services.AddMvc(options => options.Filters.Add(new AuthorizeFilter())).SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

在视图Login中创建登录页面

@model LoginViewModel

@{ Layout = null; }
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
<div class="row">
    <div class="col-md-8">

        <form asp-action="Login">
            <input type="hidden" name="returnUrl" value="@ViewBag.ReturnUrl" />
            <h4>帐户登录</h4>
            <hr />
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Email" class="control-label"></label>
                <input asp-for="Email" class="form-control" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Password" class="control-label"></label>
                <input asp-for="Password" type="password" class="form-control" />
                <span asp-validation-for="Password" class="text-danger"></span>
            </div>
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <div class="checkbox">
                        @Html.CheckBoxFor(m => m.RememberMe)
                        @Html.LabelFor(m => m.RememberMe)
                    </div>
                </div>
            </div>
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="登录" class="btn btn-success" />
                </div>
            </div>

        </form>


        

    </div>
</div>
@section Scripts {
    @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
//登录的model 
public class LoginViewModel
    {
        [Required]
        [Display(Name = "电子邮件")]
        [EmailAddress]
        public string Email { get; set; }

        [Required]
        [DataType(DataType.Password)]
        [Display(Name = "密码")]
        public string Password { get; set; }

        [Display(Name = "记住我?")]
        public bool RememberMe { get; set; }
    }

我们登录的Controller如下

 public class AccountController : Controller
    {
        [AllowAnonymous]
        public IActionResult Login(string returnUrl)
        {
            if (string.IsNullOrWhiteSpace(returnUrl))
            {
                returnUrl = GetAppHomeUrl();
            }
            ViewBag.ReturnUrl = returnUrl;
            return View();
        }
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Login(LoginViewModel model, string returnUrl)
        {            
            if (model.Email.Equals("admin@admin.com") && model.Password.Equals("123qwe"))
            {
                var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Name, model.Email),

            };
                var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), new AuthenticationProperties
                {
                    IsPersistent = true,
                    RedirectUri = returnUrl,
                    ExpiresUtc = DateTime.Now.AddSeconds(5)//每访问一下页面会添加一下访问时间,如果时间到期,会跳转到登录页面
                });
                return RedirectToLocal(returnUrl);
            }
            else
            {
                return View();
            }


        }
        public async Task<IActionResult> LogOut()
        {
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            return RedirectToAction("Login");
        }
        /// <summary>
        /// 重定项
        /// </summary>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        private ActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            return RedirectToAction("Index", "Home");
        }
        public string GetAppHomeUrl()
        {
            return Url.Action("Index", "Home");
        }
    }

到此为止现在的框架基本都差不多了,适合小型项目的使用了,但是还有一个问题就是如果咱们的实体类过多的情况下,需要依赖注入代码量庞大,所以咱们要写一个通用的方法来批量依赖注入,现在来看依赖注入的代码

/// <summary>
    /// 先创建一个抽象类
    /// </summary>
    public abstract class IocManager
    {
        public static void Register(IServiceCollection services)
        {
            Type type = typeof(IDependency);//获取继承IDependency的类型
            //从程序集中找到包含IDependency所有相关
            var Types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(type) || t.GetInterfaces().Contains(type)));
            //得到类的集合
            var classList = Types.Where(o => o.IsClass).ToList();
            //得到接口的集合
            var InterfaceList = Types.Where(o => o.IsInterface).ToList();
            foreach (var item in classList)
            {
                var firstInterface = InterfaceList.FirstOrDefault(o => o.IsAssignableFrom(item));//class有接口,注入接口和类
                if (firstInterface != null)
                {
                    services.AddScoped(firstInterface, item);
                }
                else
                {
                    //注入class
                    services.AddScoped(item);
                }
            }
            //派生类注入
            services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
            services.AddScoped(typeof(IAsyncCrudAppService<>), typeof(AsyncCrudAppService<>));

        }
    }

在Startup.ConfigureServices中注入

 //批量依赖注入
IocManager.Register(services);

创建一个IDependency接口

 public interface IDependency
    {
    }

在我们的IService中继承IDependency

 public interface IUserService : IAsyncCrudAppService<Users>, IDependency
    {
    }

就到此结束结束了

[外链图片转存中...(img-IkcgurWo-1619617941975)]

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值