zoukankan      html  css  js  c++  java
  • 用VSCode开发一个基于asp.net core 2.0/sql server linux(docker)/ng5/bs4的项目(3)

    第一部分: http://www.cnblogs.com/cgzl/p/8478993.html

    第二部分: http://www.cnblogs.com/cgzl/p/8481825.html

    由于本文主要是讲VSCode开发等, 所以相关等一些angular/.net core的知识就相对少讲点.

    我把需求改一下, 如图:

    由于efcore目前还是使用中间表来建立多对多的关系, 所以分类标签这个需求就没什么特别的了, 就去掉吧. 还有电视剧分季这个技术上也是重复的, 也删掉.

    目前只剩下电视台和电视剧的维护, 还剩下的知识点是:

    • 集合的CRUD操作
    • 对项目结构进行整理, 使用Unit Of Work 以及 Repository 模式
    • 上传文件

    由于CRUD画面做起来比较简单, 我相信大家使用该技术的都会, 所以我直接把我写完的代码传上来. 此时页面的操作效果请看视频:

    这时的代码: 

    https://pan.baidu.com/s/1egCmuNT0OxJNwkz0OQ72kA

    这里面又一个比较常见的问题, 就是

    针对集合的增删改:

    上述业务的电视剧的增删改就会出现这种情况:

    数据库里面原来有4条数据, 而前台操作完, 删除了第3条数据, 并且增加了一条数据, 其余数据的内容可能有变化.

    这种集合类增删改的思路应该是这样的:

    1.从传进来的集合找出所有新添加的数据(新添加的数据Id通常并不存在, 这是条件), 放在一个临时的集合, 然后添加到context.

    2.从数据库集合找出所有需要删除的数据(有一些id在传进来的集合找不到的就是), 放在一个集合, 然后从conetxt一次性移除.

    3.两个集合都有的数据就是只需要修改内容的数据, 更新即可.

    下面开始实现这个功能:

    首先确保Put方法里, 把电视台下所有的电视剧都读取出来:

     

    接下来, 找到MappingProfile.cs, 使用AutoMapper来实现这个功能.

    首先要忽略默认的集合映射:

    然后调用AfterMap方法做后期手动处理, 代码的意思大概是这样:

    或者, 也可以用Linq做一些重构:

    回到画面试一下编辑功能:

    然后添加和删除:

    查看结果:

    OK.

    项目重构

    下面, 我们使用Unit Of Work以及Repository Pattern对项目进行重构:

    由于这部分也很简单, 并且也不是这篇文章的重点, 我就直接贴出重构后的代码吧:

    Database/TvRepostiory.cs:

    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Microsoft.EntityFrameworkCore;
    using Tv.Models;
    
    namespace Tv.Database
    {
        public class TvRepository : ITvRepostitory
        {
            private readonly TvContext context;
    
            public TvRepository(TvContext context)
            {
                this.context = context;
            }
    
            public async Task<List<TvNetwork>> GetTvNetworksAsync()
            {
                return await context.TvNetworks.Include(x => x.TvShows).ToListAsync();
            }
    
            public async Task<TvNetwork> GetTvNetworkByIdAsync(int id, bool includeRelated = true)
            {
                if (includeRelated)
                {
                    return await context.TvNetworks.Include(x => x.TvShows).SingleOrDefaultAsync(x => x.Id == id);
                }
                return await context.TvNetworks.FindAsync(id);
            }
    
            public void AddTvNetwork(TvNetwork model)
            {
                context.TvNetworks.Add(model);
            }
    
            public void RemoveTvNetwork(TvNetwork model)
            {
                context.TvNetworks.Remove(model);
            }
        }
    }

    Database/ITvRepository.cs:

    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Tv.Models;
    
    namespace Tv.Database
    {
        public interface ITvRepostitory
        {
            Task<List<TvNetwork>> GetTvNetworksAsync();
            Task<TvNetwork> GetTvNetworkByIdAsync(int id, bool includeRelated = true);
            void AddTvNetwork(TvNetwork model);
            void RemoveTvNetwork(TvNetwork model);
        }
    }

    Database/UnitOfWork.cs:

    using System.Threading.Tasks;
    
    namespace Tv.Database
    {
        public class UnitOfWork : IUnitOfWork
        {
            private readonly TvContext context;
    
            public UnitOfWork(TvContext context)
            {
                this.context = context;
            }
    
            public async Task SaveAsync()
            {
                await context.SaveChangesAsync();
            }
        }
    }

    Database/IUnitOfWork.cs:

    using System.Threading.Tasks;
    
    namespace Tv.Database
    {
        public interface IUnitOfWork
        {
            Task SaveAsync();
        }
    }

    Startup.cs:

    public void ConfigureServices(IServiceCollection services)
            {
                services.AddAutoMapper();
                // services.AddDbContext<TvContext>(opt => opt.UseSqlServer(Configuration["ConnectionStrings:Default"]));
                services.AddDbContext<TvContext>(opt => opt.UseSqlServer(Configuration.GetConnectionString("Default")));
                services.AddScoped<ITvRepostitory, TvRepository>();
                services.AddScoped<IUnitOfWork, UnitOfWork>();
                services.AddMvc();
            }

    TvController.cs:

    using System.Collections.Generic;
    using System.Threading.Tasks;
    using AutoMapper;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using Tv.Database;
    using Tv.Models;
    using Tv.ViewModels;
    
    namespace Tv.Controllers
    {
        public class TvController : Controller
        {
            private readonly ITvRepostitory repostiory;
            private readonly IUnitOfWork unitOfWork;
            private readonly IMapper mapper;
    
            public TvController(ITvRepostitory repostiory, IUnitOfWork unitOfWork, IMapper mapper)
            {
                this.repostiory = repostiory;
                this.unitOfWork = unitOfWork;
                this.mapper = mapper;
            }
    
            [HttpGet("api/tvnetworks")]
            public async Task<IEnumerable<TvNetworkViewModel>> GetTvNetworks()
            {
                var models = await repostiory.GetTvNetworksAsync();
                var vms = mapper.Map<List<TvNetwork>, List<TvNetworkViewModel>>(models);
                return vms;
            }
    
            [HttpGet("api/tvnetworks/{id}")]
            public async Task<IActionResult> Get(int id)
            {
                var model = await repostiory.GetTvNetworkByIdAsync(id);
                var vm = mapper.Map<TvNetwork, TvNetworkViewModel>(model);
                return Ok(vm);
            }
    
            [HttpPost("api/tvnetworks")]
            public async Task<IActionResult> Post([FromBody]TvNetworkUpdateViewModel vm)
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState);
                }
                var model = mapper.Map<TvNetworkUpdateViewModel, TvNetwork>(vm);
                repostiory.AddTvNetwork(model);
                await unitOfWork.SaveAsync();
                var result = mapper.Map<TvNetwork, TvNetworkViewModel>(model);
                return Ok(result);
            }
    
            [HttpPut("api/tvnetworks/{id}")]
            public async Task<IActionResult> Put(int id, [FromBody]TvNetworkUpdateViewModel vm)
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(ModelState);
                }
                var dbModel = await repostiory.GetTvNetworkByIdAsync(id);
                if (dbModel == null)
                {
                    return NotFound();
                }
                var model = mapper.Map<TvNetworkUpdateViewModel, TvNetwork>(vm, dbModel);
                await unitOfWork.SaveAsync();
                var result = mapper.Map<TvNetwork, TvNetworkViewModel>(model);
                return Ok(result);
            }
    
            [HttpDelete("api/tvnetworks/{id}")]
            public async Task<IActionResult> Delete(int id)
            {
                var model = await repostiory.GetTvNetworkByIdAsync(id, includeRelated: false);
                if (model == null)
                {
                    return NotFound();
                }
                repostiory.RemoveTvNetwork(model);
                await unitOfWork.SaveAsync();
                return NoContent();
            }
        }
    }

    再操作下画面, 没有任何问题.

    今天先写到这, VSCode的开发速度还是非常快的.

    还剩下最后一部分--上传文件.

  • 相关阅读:
    多线程单例模式之立即加载(饿汉模式)
    多线程单例模式之延迟加载(懒汉模式)
    java多线程之ThreadLocal
    java多线程的字符流与字节流
    java多线程生产者消费者
    深入理解多线程三
    深入理解多线程二
    深入java多线程一
    mybatis学习三
    mybatis学习二
  • 原文地址:https://www.cnblogs.com/cgzl/p/8525541.html
Copyright © 2011-2022 走看看