asp.net core2.1+EFCore + MVC开发留言管理项目实战(一)

  好久没写随笔了,主要是因为近一个月赶项目。近期翻了翻前程无忧,发现招聘要求使用.net core的公司越来越多,不得不感叹一下.net 发展,有今天的局面离不开微软粑粑的大力开源。正好自己最近也在接触学习.net core,这里打算开两三期记录一下这个小demo的开发过程,后续会附录上源代码。

  首先介绍下项目背景,本人使用的开发工具是vs2017 社区免费版,服务器是腾讯云低配版服务器(Ubuntu16.04  64位,个人随便搭建个环境玩玩,低配版跑的windows很卡,只能用linux),.net core sdk是2.1.400,web服务器采用jexus5.8.2(一开始是采用nginx,由于.netcore 运行需要前台运行,并且在关闭ssh连接之后会自动断开,因此采用jexus),数据库采用mysql。项目实现了两个小模块(增删查改),分别是分类管理和文章管理,由于是demo项目,诸位看官请勿太过计较= =||。

  首先是项目结构,项目采用EFCore Code first模式,分为实体、仓库、Service接口、Application(service实现)和WebApp(UI)。实体层包括了实体和仓库接口,仓库层包括了Dbcontext和仓库实现(简单写了个BaseRepository实现),Service接口层包括了业务接口以及dto,Application层是service业务接口的实现(相关的业务逻辑写在这层)。如下图:

    

  先看看startup

using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Ye.BoardMessage.Repository;
using Ye.BoardMessage.Entity.IRepositories;
using Ye.BoardMessage.Service;
using Ye.BoardMessage.Application;
using Microsoft.AspNetCore.Authentication.Cookies;

namespace Ye.BoardMessage.WebApp
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //DbContext
            services.AddDbContext<BoardMessageDbContext>((provider, builder) =>
            {
                builder.UseMySql(Configuration.GetConnectionString("DefaultConnection"), b =>
                {
                    b.CommandTimeout(10);
                });
            });
           //服务注入
            services.AddLogging();
            services.Add(new ServiceDescriptor(typeof(DbContext), typeof(BoardMessageDbContext), ServiceLifetime.Scoped));
            services.Add(new ServiceDescriptor(typeof(ICategoryRepository), typeof(CategoryRepository), ServiceLifetime.Scoped));
            services.Add(new ServiceDescriptor(typeof(IMsgArticleRepository), typeof(MsgArticleRepository), ServiceLifetime.Scoped));
            services.Add(new ServiceDescriptor(typeof(IAppUserRepository), typeof(AppUserRepository),ServiceLifetime.Scoped));
            services.Add(new ServiceDescriptor(typeof(ICategoryService), typeof(CategoryService), ServiceLifetime.Scoped));
            services.Add(new ServiceDescriptor(typeof(IMsgArticleService), typeof(MsgArticleService), ServiceLifetime.Scoped));
            services.Add(new ServiceDescriptor(typeof(IAppUserService), typeof(AppUserService), ServiceLifetime.Scoped));

            //https://www.cnblogs.com/oorz/p/8617530.html cookie授权登录参考
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,options =>
                {
                    options.Cookie.HttpOnly = true;
                    options.Cookie.Expiration = TimeSpan.FromMinutes(30);
                    // If the LoginPath isn't set, ASP.NET Core defaults 
                    // the path to /Account/Login.
                    options.LoginPath = "/Account/Login";
                    options.Cookie.Name = CookieAuthenticationDefaults.AuthenticationScheme;
                });
            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }
            
            app.UseStaticFiles();
            app.UseCookiePolicy();
            
            app.UseAuthentication();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

  然后是DbContext以及相关的Entity和EntityMap

  1、DbContext实现

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Text;
using Ye.BoardMessage.Repository.EntityMaps;

namespace Ye.BoardMessage.Repository
{
    public class BoardMessageDbContext : DbContext
    {
        public BoardMessageDbContext() : base()
        {
        }

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

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.ApplyConfiguration(new CategoryEntityMap());
            modelBuilder.ApplyConfiguration(new MsgArticleEntityMap());
            modelBuilder.ApplyConfiguration(new AppUserEntityMap());
            base.OnModelCreating(modelBuilder);
        }
    }
}

  2、Entity,这里因为Entity比较多,因此只选取一个来做介绍,这个是留言的实体

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;

namespace Ye.BoardMessage.Entity
{
    public class MsgArticleEntity
    {
        public int Id { get; set; }

        public string Title { get; set; }

        public string Author { get; set; }

        public DateTime CreatedTime { get; set; }

        public string MsgContent { get; set; }

        public int CategoryId { get; set; }
        
        public CategoryEntity Category { get; set; }
    }
}

  3、EntityMap,同样因为Map比较多,只选取一个来做介绍,留言实体映射

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Text;
using Ye.BoardMessage.Entity;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Ye.BoardMessage.Repository.EntityMaps
{
    public class MsgArticleEntityMap : IEntityTypeConfiguration<MsgArticleEntity>
    {
        public void Configure(EntityTypeBuilder<MsgArticleEntity> builder)
        {
            builder.ToTable("messagearticle");
            builder.HasKey(t => t.Id);
            builder.Property(t => t.Id).HasColumnName("Id");
            builder.Property(t => t.Author).HasColumnName("Author").IsRequired().HasMaxLength(30);
            builder.Property(t => t.CategoryId).HasColumnName("CategoryId").IsRequired();
            builder.Property(t => t.CreatedTime).HasColumnName("CreatedTime").IsRequired();
            builder.Property(t => t.MsgContent).HasColumnName("MsgContent").IsRequired().HasMaxLength(500);
            
            builder.HasOne<CategoryEntity>(t => t.Category)
                .WithMany(p => p.Articles).HasForeignKey(p => p.CategoryId).IsRequired();
        }
    }
}

  总的来说,EFCore相比EntityFramework,API方面略有改变,大体用法还是一致的,另外asp.net core自带了服务注入,这个非常方便。EFCore一对多的配置有所改变,这里踩了个小坑的,参阅了网上不少资料才填完(感谢发达的网络- -b)。这个系列的第一篇介绍完毕,下一篇将介绍使用cookie登录验证以及BaseRepository。代码后续会贴出来,各位看官莫急。

posted @ 2018-10-03 00:23  尋找一個證明  阅读(2405)  评论(0编辑  收藏  举报