当前位置:Gxlcms > 数据库问题 > Asp.net Core基于MVC框架实现PostgreSQL操作

Asp.net Core基于MVC框架实现PostgreSQL操作

时间:2021-07-01 10:21:17 帮助过:2人阅读

The following providers are available

  • Microsoft SQL Server
  • SQLite
  • Npgsql (PostgreSQL)
  • Microsoft SQL Server Compact Edition
  • IBM Data Servers
  • InMemory (for Testing)
  • Devart (MySQL, Oracle, PostgreSQL, SQLite, DB2, SQL Server, and more)
  • MySQL (Coming Soon)
  • Oracle (Coming Soon)

所以提供给我们选择的数据库还是有限的(主要是不支持MySql,Devart这东西笔者不了解,不评论)。总得来说,对MS SQL Server的支持肯定是最好的,所以场景允许下,首选Sql server。其次,就DB2和PostgreSQL可选了。笔者不喜欢DB2(很多原因,主要是开发操作管理麻烦,并非说DB2本身存在问题),PostgreSQL其实也不太好用,不过谁叫他免费呢,肯定是好多国内公司首选。

PostgreSQL本身历史悠久,记得好像上世纪80年代就存在了,免费开源,而且是有专门社区维护。设计理念是以健壮性为首选,所以收到光打企业级平台欢迎。关于PostgreSQL和MySQL之间的优缺点,这个其实不太好说,MySQL在损失健壮性的同时,提高了性能,并且支持很多非标准新特性,而PostgreSQL在健壮性上,号称不弱于Oracle,性能优秀,完全支持SQL标准,所以其实并不差。

准备环境

Ubuntu Server(16.04)虚拟机1台,IP:192.168.1.6 预装了PostgreSQL数据库,并配置好防火墙,ssh连接等基础环境。确保能够外部访问。

VS2015 Update3

Putty 和SSH Secure File Transfer Client

服务器环境部署

    参考之前的博客:http://blog.csdn.net/lanwilliam/article/details/51880124

开始

  1. 新建项目,选择Asp.net Core Web Application项目模板。

    技术分享

  2. 选择Web应用程序模板,然后修改身份验证哪里,选择不进行身份验证。

    技术分享

    这里要说一下,Asp.net core项目中,包含一个Identity子项目,在GitHub上有介绍如下:

    技术分享

    这里大家一看就知道了,这就是原来提供的ASP.net自带的权限框架。这个框架现在其实非常强大了,还支持Google和TWriter等OAuth用法,不过缺点是只支持SQL Server数据库。如果选择了个人用户账户,那么会默认使用这个框架创建项目。我们希望用PostgreSQL,所以不能选他,很遗憾。而且目前创建控制器等一些内置模板用法,都是基于SqlServer,用到这个Identity,大家如果看过微软的GettingStarted,就会看到介绍,所以建议大家首先学习微软GettingStarted。

    当然,不要勾选云中托管。

  3. 空白项目结构

    技术分享

    上图是新建完成的空白项目结构,你会发现Models,Data等文件夹都不存在,这里需要手动新建,并且丢进去一个class。

    技术分享

    必须要丢进去个class文件,让类定义的时候声明出Models和Data的命名空间,否则待会生成models文件的时候会报错。

  4. 增加项目引用

    Asp.net core项目有两种方法增加引用,一种是直接修改project.json,另一种是nuget。

    技术分享

    上述方法打开控制台

    技术分享

    输入如下命令

    技术分享

    会发现最后的Tools安装不了,可能nuget没同步过来,可以在project.json中手动添加。

    最后的文件如下:

    技术分享

    主要是圈选中的部分。可以看到这里我们用来操作PostgreSQL的Provider是Npgsql,这是aspnet下的一个子项目。可以在github找到。

    其他EntityFrameworkCore的引用,是从示例项目中搬来的。

  5. 生成Models文件

    这里要说明一下,微软MVC教程中时使用的模板创建的Controller,他会自动创建ApplicationDBContext和对应的Views视图文件,以及一些其他的内容。因为他更新了ApplicationDBContext文件和ApplicationDbContextModelSnapshot文件,所以控制台执行dotnet ef命令才会正常完成,这里无法用到这些方法。因为没选"个人用户账户",这里请自行尝试。

    dotnet ef migrations add Initial

    dotnet ef database update

    由于自行写DBContext类实现太麻烦,我们这里采取开发中常用的办法,首先设计数据库,然后根据数据库生成类。

    在数据库新建表如下:(测试用,看看就好)

    技术分享

    然后回到VS2015,在Nuget程序包控制台输入:

    Scaffold-DbContext "Server=192.168.1.6;Database=testdb;User ID=test;Password=test;" Npgsql.EntityFrameworkCore.PostgreSQL -OutputDir Models

    技术分享

这个命令不用解释了吧?数据库连接,使用的数据库provider和输出目录。

顺利完成的话,Models下会出现几个类文件。

技术分享

如果报错的话,请根据错误提示进行处理。处理原则,首先保证程序能够编译通过,然后确保Models下面没有存在本次要生成的同名文件,然后确认目前系统没有其他DBContext存在。现在dotnet core的好多工具都在完善中,健壮性都有待提高。

打开看看生成的文件:

技术分享 技术分享

using System;

using Microsoft.EntityFrameworkCore;

using Microsoft.EntityFrameworkCore.Metadata;

 

namespace PostgresSqlDemo.Models

{

public partial class testdbContext : DbContext

{

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

{

#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.

optionsBuilder.UseNpgsql(@"Server=192.168.1.6;Database=testdb;User ID=test;Password=test;");

}

 

protected override void OnModelCreating(ModelBuilder modelBuilder)

{

modelBuilder.Entity<Blog>(entity =>

{

entity.ToTable("blog");

 

entity.Property(e => e.Id)

.HasColumnName("id")

.ValueGeneratedNever();

 

entity.Property(e => e.Title)

.IsRequired()

.HasColumnName("title")

.HasColumnType("varchar")

.HasMaxLength(300);

 

entity.Property(e => e.Url)

.IsRequired()

.HasColumnName("url")

.HasColumnType("varchar")

.HasMaxLength(300);

});

 

modelBuilder.Entity<TbUser>(entity =>

{

entity.HasKey(e => e.Userid)

.HasName("PK_tb_user");

 

entity.ToTable("tb_user");

 

entity.Property(e => e.Userid)

.HasColumnName("userid")

.ValueGeneratedNever();

 

entity.Property(e => e.Age).HasColumnName("age");

 

entity.Property(e => e.Name)

.IsRequired()

.HasColumnName("name")

.HasColumnType("varchar")

.HasMaxLength(30);

});

}

 

public virtual DbSet<Blog> Blog { getset; }

public virtual DbSet<TbUser> TbUser { getset; }

}

}

Entityframework中,默认是一个数据库使用唯一一个DBContext类进行管理。

  1. 修改DBContext文件

    技术分享

    模板已经提示给你,需要修改这部分代码,实现动态配置连接的目的。

    进行如下修改:

    技术分享

    注释掉OnConfiguring方法,增加构造函数,我们把注册放到Startup中去完成。

  2. 添加数据库连接配置项

    打开appsetting.json文件,增加如下配置:

    技术分享

    其实这就相当于原来asp.net中的Web.config中的ConnectionStrings。

  3. 注册DBContext

    打开StartUP.cs 文件,找到ConfigureServices方法,添加选中代码:

    技术分享

        到这里就看明白了吧,注册DBContext,使用Npgsql,并给出数据库连接字符串。

  1. 增加控制器Controller

    在Controller文件夹下新建Controller文件,并添加如下代码:

    using Microsoft.AspNetCore.Mvc;

    using PostgresSqlDemo.Data;

    using PostgresSqlDemo.Models;

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Threading.Tasks;

    using Microsoft.EntityFrameworkCore;

     

    namespace PostgresSqlDemo.Controllers

    {

    public class TbUserController : Controller

    {

    private readonly testdbContext _context;

     

    public TbUserController(testdbContext context)

    {

    _context = context;

    }

     

    // GET: tbusers

    public async Task<IActionResult> Index()

    {

    return View(await _context.TbUser.ToListAsync());

    }

     

    public async Task<IActionResult> Details(Guid? id)

    {

    if (id == null)

    {

    return NotFound();

    }

     

    var tbuser = await _context.TbUser.SingleOrDefaultAsync(m => m.Userid == id);

    if (tbuser == null)

    {

    return NotFound();

    }

     

    return View(tbuser);

    }

     

    // GET: tbusers/Create

    public IActionResult Create()

    {

    return View();

    }

     

    // POST: tbusers/Create

    // To protect from overposting attacks, please enable the specific properties you want to bind to, for

    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.

    [HttpPost]

    [ValidateAntiForgeryToken]

    public async Task<IActionResult> Create([Bind("Userid,Name,Age")] TbUser tbuser)

    {

    if (ModelState.IsValid)

    {

    tbuser.Userid = Guid.NewGuid();

    _context.Add(tbuser);

    await _context.SaveChangesAsync();

    return RedirectToAction("Index");

    }

    return View(tbuser);

    }

     

    // GET: tbusers/Edit/5

    public async Task<IActionResult> Edit(Guid? id)

    {

    if (id == null)

    {

    return NotFound();

    }

     

    var tbuser = await _context.TbUser.SingleOrDefaultAsync(m => m.Userid == id);

    if (tbuser == null)

    {

    return NotFound();

    }

    return View(tbuser);

    }

     

    // POST: tbusers/Edit/5

    // To protect from overposting attacks, please enable the specific properties you want to bind to, for

    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.

    [HttpPost]

    [ValidateAntiForgeryToken]

    public async Task<IActionResult> Edit(Guid id, [Bind("Userid,Name,Age")] TbUser tbuser)

    {

    if (id != tbuser.Userid)

    {

    return NotFound();

    }

     

    if (ModelState.IsValid)

    {

    try

    {

    _context.Update(tbuser);

    await _context.SaveChangesAsync();

    }

    catch (DbUpdateConcurrencyException)

    {

    if (!tbuserExists(tbuser.Userid))

    {

    return NotFound();

    }

    else

    {

    throw;

    }

    }

    return RedirectToAction("Index");

    }

    return View(tbuser);

    }

     

    // GET: tbusers/Delete/5

    public async Task<IActionResult> Delete(Guid? id)

    {

    if (id == null)

    {

    return NotFound();

    }

     

    var tbuser = await _context.TbUser.SingleOrDefaultAsync(m => m.Userid == id);

    if (tbuser == null)

    {

    return NotFound();

    }

     

    return View(tbuser);

    }

     

    // POST: tbusers/Delete/5

    [HttpPostActionName("Delete")]

    [ValidateAntiForgeryToken]

    public async Task<IActionResult> DeleteConfirmed(Guid id)

    {

    var tbuser = await _context.TbUser.SingleOrDefaultAsync(m => m.Userid == id);

    _context.TbUser.Remove(tbuser);

    await _context.SaveChangesAsync();

    return RedirectToAction("Index");

人气教程排行