Asp.netCore3.0 WebApi从0到1手摸手教你写【2】通过EF访问数据库

今天要增加一个通过EF访问数据库的功能,同时写一个增加新用户的接口,
接口访问地址:api/User/AddUser
接口入参:{ "phone":"13200000000", "password":"123456", "nickName":"小赵先生", "state":1 }
接口返回值:{ "code": 1, "message": "数据插入成功" }

开发环境

Visual Studio 2019
.net core 3.0
Sqlserver 2008数据库
Postman

第一步创建类库

教程一的基础上首先新增3个.NET Core类库----ModelsBoCommon
Models:存放EF的一些实体类,EF的DBContent和接口传参Model以及接口返回值Model等一切和对象有关的统统放这里。
Bo:这里主要处理业务层面的事情,比如将用户信息存放到数据库。
Common:主要是一些公共类,比如图片上传、Md5签名、DES加密解密等。
创建类库具体步骤如下图:

01

02

03

创建好类库以后可以把里面的Class1.cs直接删除
04

添加完类库以后进行类库的关联,API引用Models+Bo+CommonBo引用Models+Common
05

3个类库创建完毕以后整个工程目录如下:
项目目录

然后给每个项目添加EF相关的Nuget包,每个类库要添加的包如下:


EF包添加

这个项目有点.Net三层架构的意思,没有用工场模式,解耦方面也没有特别的考虑,优点就是简单、清晰、一目了然,可以满足小型和中型项目,做个后台管理系统接口或者手机APP接口完全没有问题。

第二步创建一个数据库

一个EF项目的开始总会有人在思考到底DBFirs还是CodeFirst,个人还是比较喜欢DBFirst,数据库设计好了,剩下的项目代码其实90%以上就是数据库的增删改查操作了,所以这个教程也是采用的DBFirst模式。
数据库怎么创建就不写教程了,直接给代码:
数据库名称:xxx
表名称:User
表创建代码如下:

CREATE TABLE [dbo].[User](
    [id] [int] IDENTITY(1,1) NOT NULL,--一个自动增长的主键
    [phone] [varchar](20) NULL,--用户手机号
    [password] [nvarchar](50) NULL,--用户密码
    [msgCode] [varchar](10) NULL,--用户最新一次获取的短信验证码
    [regTime] [datetime] NULL,--用户注册时间
    [nickName] [nvarchar](50) NULL,--用户昵称
    [state] [int] NULL,--用户状态
 CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

注:此处应该说一句,不推荐给表起名User,User在sqlserver中属于关键词,所以在写sql语句的时候要把User表名括起来,比如:select * from [User]

第三步EF相关代码

在Models中XXXEntities中新建2个类,一个表User实体类User.cs和DbContext类xxxContext.cs


User.cs代码如下:

using System;

namespace XXX.Models.XXXEntities
{
    public partial class User
    {
        public int Id { get; set; }
        public string Phone { get; set; }
        public string Password { get; set; }
        public string MsgCode { get; set; }
        public DateTime? RegTime { get; set; } //此处的问号表示RegTime允许为空
        public string NickName { get; set; }
        public int? State { get; set; }
    }
}

xxxContext.cs代码如下:

using Microsoft.EntityFrameworkCore;

namespace XXX.Models.XXXEntities
{
    public partial class xxxContext : DbContext
    {
        public xxxContext()
        {
        }

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

        public virtual DbSet<User> User { get; set; }
        public static string ConStr { get; set; }//用于接收数据库连接字符串
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer(ConStr);//设置数据库连接字符串
            }
        }
    }
}

注:如果数据库表非常多,手写数据库表实体类是一件非常烦躁且容易出错的事情,所以可以使用命令自动生成。
1.打开程序包管理器控制台

操作步骤

控制台界面如下:
控制台界面

2.在控制台输入命令代码,默认项目要选择xxx.Models这样才能把代码生成到Models里面
Scaffold-DbContext "Server=服务器地址;User Id=用户名;Password=密码;Database=数据库名称;" Microsoft.EntityFrameworkCore.SqlServer -o XXXEntities -f -t StateMgr
注意事项

注释:
-o 后面指定文件夹,
-f 表示是否覆盖原文件
-t 后面跟表名
默认生成的xxxContext.cs自动把数据库连接字符串写在项目中了,这样不便于后期维护,推荐写在配置文件中。

OnConfiguring

第四步配置数据库连接字符串

  1. 在XXX.api项目中找到appsettings.json文件增加数据库连接字符串
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "xxxDB": "Server=服务器地址;User Id=数据库登录名;Password=密码;Database=数据库名称;"
  }
}
  1. 在XXX.api项目中找到Startup.cs文件获取数据库连接字符串

    也可以通过services.AddDbContext<Models.XXXEntities.xxxContext>(options => { options.UseSqlServer(conn); });注册数据库连接字符串,但是EF的实体类放在了Models中不知道为什么这样写总提示没有配置数据库,于是改成了通过一个全局变量来设置数据库连接字符串的方式。
    关于EF相关的写完了,下面开始写一个接口。

第五步定义接口

  1. 在XXX.Bo中新建一个UserBo.cs
using System.Linq;

namespace XXX.Bo
{
    public class UserBo
    {
        public static Models.XXXEntities.xxxContext db = new Models.XXXEntities.xxxContext();
        /// <summary>
        /// 增加一个用户数据
        /// </summary>
        /// <param name="model"></param>
        public static Models.User.AddUserR AddUser(Models.User.AddUserP model)
        {
            
            var r = new Models.User.AddUserR();
            Models.XXXEntities.User userSearch = (from u in db.User where u.Phone == model.phone select u).FirstOrDefault();
            if (userSearch==null)
            {
                Models.XXXEntities.User user = new Models.XXXEntities.User();
                user.Phone = model.phone;
                user.Password = model.password;
                user.NickName = model.nickName;
                user.State = model.state;
                db.User.Add(user);
                int i =db.SaveChanges();
                if (i>0)
                {
                    r.code = 1;
                    r.message = "数据插入成功";
                }
                else
                {
                    r.code = 0;
                    r.message = "数据插入成功";
                }
            }
            else
            {
                r.code = 0;
                r.message = "手机号已经存在";
            }
            return r;
        }
    }
}
//EF我是用Linq的方式写的,所以using只引用了System.Ling
  1. 在XXX.api中UserController.cs增加一个接口
        /// <summary>
        /// 增加一个用户
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddUser([FromBody]Models.User.AddUserP model)
        {
            var r = Bo.UserBo.AddUser(model);
            return Ok(r);
        }

第六步测试

接口写好了,程序员要自己测试下代码,这是一个非常好的习惯,要从写第一行代码开始就要养成,我们测试下
打开postman输入测试数据和接口地址,红框里是需要注意的内容


image.png

我们打个断点查看下webapi接收到的数据


post数据接收

第一次提交返回结果
结果1

第二次提交返回结果
结果2

通过这2个教程基本上就掌握如何用NetCore写一个webapi了,不过接口写好了是不是该提供一份棒棒的接口文档呢?答案必须是YES,下一个教程将带你去给接口生成一个棒棒的接口文档。

补充

Models类库

Models

注:P结尾的model表示参数实体对象,R结尾的model表示返回结果实体对象
AddUserP.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace XXX.Models.User
{
    public class AddUserP
    {
        public string phone { get; set; }
        public string password { get; set; }
        public string nickName { get; set; }
        public int state { get; set; }
        public string sign { get; set; }
    }
}

AddUserR.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace XXX.Models.User
{
    public class AddUserR
    {
        public int code { get; set; }
        public string message { get; set; }
    }
}

项目源码地址

https://github.com/xiaxiaoqian/NetCore3.0-WebApi

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容