简单介绍
Asp.net Core最大的价值在于跨平台、跨平台、跨平台。重要的事情说三遍。但是目前毕竟是在开发初期,虽然推出了1.0.0 正式版,但是其实好多功能还没有完善。比方说编译时的一些文件编码问题,辅助工具Tools的一些Bug,还有一些好用的模板和平台实现尚未完成等一些问题。但这毕竟是一个好的开始,并且在Github上,大家都还在积极的完善,你也可以参与进来。地址:https://github.com/aspnet
Asp.net Core在学习的时候,首先你应该跟着微软官方的入门教材来学习,在这里: https://docs.asp.net/en/latest/tutorials/first-mvc-app/start-mvc.html。这个入门教材很浅显易懂的让你了解了Asp.net Core mvc框架以及entity framework core的用法。不过缺点是,使用的是Sql compact数据库,也就是SQL Server数据库。要知道,我们使用Asp.net 的主要目的是实现跨平台部署,所以数据库的选择上,首选肯定不是SqlServer,否则意义何在?当然,目前Entity Framework core暂时还不支持所有数据库。截止2016年7月,支持情况如下:
Database Providers
The following providers are available
所以提供给我们选择的数据库还是有限的(主要是不支持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
开始
-
新建项目,选择Asp.net Core Web Application项目模板。
-
选择Web应用程序模板,然后修改身份验证哪里,选择不进行身份验证。
这里要说一下,Asp.net core项目中,包含一个Identity子项目,在GitHub上有介绍如下:
这里大家一看就知道了,这就是原来提供的ASP.net自带的权限框架。这个框架现在其实非常强大了,还支持Google和TWriter等OAuth用法,不过缺点是只支持SQL Server数据库。如果选择了个人用户账户,那么会默认使用这个框架创建项目。我们希望用PostgreSQL,所以不能选他,很遗憾。而且目前创建控制器等一些内置模板用法,都是基于SqlServer,用到这个Identity,大家如果看过微软的GettingStarted,就会看到介绍,所以建议大家首先学习微软GettingStarted。
当然,不要勾选云中托管。
-
空白项目结构
上图是新建完成的空白项目结构,你会发现Models,Data等文件夹都不存在,这里需要手动新建,并且丢进去一个class。
必须要丢进去个class文件,让类定义的时候声明出Models和Data的命名空间,否则待会生成models文件的时候会报错。
-
增加项目引用
Asp.net core项目有两种方法增加引用,一种是直接修改project.json,另一种是nuget。
上述方法打开控制台
输入如下命令
会发现最后的Tools安装不了,可能nuget没同步过来,可以在project.json中手动添加。
最后的文件如下:
主要是圈选中的部分。可以看到这里我们用来操作PostgreSQL的Provider是Npgsql,这是aspnet下的一个子项目。可以在github找到。
其他EntityFrameworkCore的引用,是从示例项目中搬来的。
-
生成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 { get; set; }
public
virtual
DbSet<TbUser> TbUser { get; set; }
}
}
Entityframework中,默认是一个数据库使用唯一一个DBContext类进行管理。
-
修改DBContext文件
模板已经提示给你,需要修改这部分代码,实现动态配置连接的目的。
进行如下修改:
注释掉OnConfiguring方法,增加构造函数,我们把注册放到Startup中去完成。
-
添加数据库连接配置项
打开appsetting.json文件,增加如下配置:
其实这就相当于原来asp.net中的Web.config中的ConnectionStrings。
-
注册DBContext
打开StartUP.cs 文件,找到ConfigureServices方法,添加选中代码:
到这里就看明白了吧,注册DBContext,使用Npgsql,并给出数据库连接字符串。
-
增加控制器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
[HttpPost, ActionName("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");
}
private
bool tbuserExists(Guid id){
return _context.TbUser.Any(e => e.Userid == id);
}
}
}
如果你看过Getting Started Asp.net core MVC的话,相信应该能够看懂,基本是把使用新增Controller模板生成的方法修改了一下拿过来用了。
Asp.net core mvc中,默认路由名成为(name)Controller,所以我们这里叫TbUserController,访问的时候是http://youip/TbUser这样。并且默认是触发Index方法。
Controller中,每个方法,都相当于一个客户端Form的Action。没有特殊声明的方法,默认为HttpGet,可以直接请求。需要Post数据的,请手动增加[HttpPost]声明。
Async是C# 5.0后提供的关键字,是自动实现一个异步的方法,需要配合await关键字使用。Await会被自动转换为一个async的异步请求,后面的代码,会被自动放到completed方法中执行。这样处理能够极大的提高服务器的并发性能,具体请自行学习。
-
增加Views页面
增加对应的页面如下:
Index.cshtml
@model IEnumerable<PostgresSqlDemo.Models.TbUser>
@{
ViewData["Title"] = "Index";
}
<h2>Index</h2>
<p>
<a
asp-action="Create">Create New</a>
</p>
<table
class="table">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Userid)
</th>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Age)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Userid)
</td>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Age)
</td>
<td>
<a
asp-action="Edit"
asp-route-id="@item.Userid">Edit</a> |
<a
asp-action="Details"
asp-route-id="@item.Userid">Details</a> |
<a
asp-action="Delete"
asp-route-id="@item.Userid">Delete</a>
</td>
</tr>
}
</tbody>
</table>
Create.cshtml
@model PostgresSqlDemo.Models.TbUser
@{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<form
asp-action="Create">
<div
class="form-horizontal">
<h4>TbUser</h4>
<hr
/>
<div
asp-validation-summary="ModelOnly"
class="text-danger"></div>
<div
class="form-group">
<label
asp-for="Name"
class="col-md-2 control-label"></label>
<div
class="col-md-10">
<input
asp-for="Name"
class="form-control"
/>
<span
asp-validation-for="Name"
class="text-danger"
/>
</div>
</div>
<div
class="form-group">
<label
asp-for="Age"
class="col-md-2 control-label"></label>
<div
class="col-md-10">
<input
asp-for="Age"
class="form-control"
/>
<span
asp-validation-for="Age"
class="text-danger"
/>
</div>
</div>
<div
class="form-group">
<div
class="col-md-offset-2 col-md-10">
<input
type="submit"
value="Create"
class="btn btn-default"
/>
</div>
</div>
</div>
</form>
<div>
<a
asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Delete.cshtml
@model PostgresSqlDemo.Models.TbUser
@{
ViewData["Title"] = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<div>
<h4>Blog</h4>
<hr
/>
<dl
class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Userid)
</dt>
<dd>
@Html.DisplayFor(model => model.Userid)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd>
@Html.DisplayFor(model => model.Name)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Age)
</dt>
<dd>
@Html.DisplayFor(model => model.Age)
</dd>
</dl>
<form
asp-action="Delete">
<div
class="form-actions no-color">
<input
type="submit"
value="Delete"
class="btn btn-default"
/> |
<a
asp-action="Index">Back to List</a>
</div>
</form>
</div>
Details.cshtml
@model PostgresSqlDemo.Models.TbUser
@{
ViewData["Title"] = "Details";
}
<h2>Details</h2>
<div>
<h4>Blog</h4>
<hr
/>
<dl
class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.Userid)
</dt>
<dd>
@Html.DisplayFor(model => model.Userid)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd>
@Html.DisplayFor(model => model.Name)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Age)
</dt>
<dd>
@Html.DisplayFor(model => model.Age)
</dd>
</dl>
</div>
<div>
<a
asp-action="Edit"
asp-route-id="@Model.Userid">Edit</a> |
<a
asp-action="Index">Back to List</a>
</div>
Edit.cshtml
@model PostgresSqlDemo.Models.TbUser
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<form
asp-action="Edit">
<div
class="form-horizontal">
<h4>Blog</h4>
<hr
/>
<div
asp-validation-summary="ModelOnly"
class="text-danger"></div>
<input
type="hidden"
asp-for="Userid"
/>
<div
class="form-group">
<label
asp-for="Name"
class="col-md-2 control-label"></label>
<div
class="col-md-10">
<input
asp-for="Name"
class="form-control"
/>
<span
asp-validation-for="Name"
class="text-danger"
/>
</div>
</div>
<div
class="form-group">
<label
asp-for="Age"
class="col-md-2 control-label"></label>
<div
class="col-md-10">
<input
asp-for="Age"
class="form-control"
/>
<span
asp-validation-for="Age"
class="text-danger"
/>
</div>
</div>
<div
class="form-group">
<div
class="col-md-offset-2 col-md-10">
<input
type="submit"
value="Save"
class="btn btn-default"
/>
</div>
</div>
</div>
</form>
<div>
<a
asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
-
增加验证脚本引用View文件
<environment
names="Development"><script
src="~/lib/jquery-validation/dist/jquery.validate.js"></script><script
src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script></environment>
<environment
names="Staging,Production"><script
src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js"asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator">
</script>
<script
src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive">
</script>
</environment>
-
修改Layout.cshtml文件
增加如上两个连接。Blog的添加参考TbUser。这里主要是想让大家看出来DBContext的用法,所以特意弄了两个实体类。
-
然后vs里面可以运行了,效果如下:
这里没有改默认的页面。
再看我们加的页面。
并且asp.net mvc默认使用了bootstrap,所以我们可以用chrome的手机模式看看。
-
改成中文显示
改一下TbUser.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace PostgresSqlDemo.Models
{
public
partial
class
TbUser{
[Display(Name = "用户编号")]
public
Guid Userid { get; set; }[Display(Name = "用户姓名")]
public
string Name { get; set; }[Display(Name = "用户年龄")]
public
int? Age { get; set; }}
}
再看看页面
- 加一下验证
改成中文验证
[Display(Name = "用户姓名")]
[StringLength(10, MinimumLength = 3,ErrorMessage = "字段{0}长度不能小于3,总长度不能大于10")]
[Required]
public
string Name { get; set; }
-
最后就是部署到Ubuntu服务器了。
将WebApp项目发布出来,使用SSH Secure File Transfer上传到服务器,然后参照前文发布。
总结:
Asp.net Core 目前来说功能性还不完善,暂时不建议大型应用往上迁移,但是如果是小型项目,比较简单,可以在仔细论证后尝试使用。注意仔细论证,因为目前.net core并不是所有类库都能够实现跨平台。简单来说,System.Drawing就无法使用,所以后台画水印就需要其他三方库,这个请自行仔细论证。不过小项目发布到linux虚拟机上面,确实可以省一笔钱。
Asp.net Core基于MVC框架实现PostgreSQL操作的更多相关文章
-
基于ASP.NET core的MVC站点开发笔记 0x01
基于ASP.NET core的MVC站点开发笔记 0x01 我的环境 OS type:mac Software:vscode Dotnet core version:2.0/3.1 dotnet sd ...
-
ASP.NET Core 配置 MVC - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 配置 MVC - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 配置 MVC 前面几章节中,我们都是基于 ASP.NET 空项目 ...
-
asp.net core的DI框架思考以及服务实例的获取方式总结
转载请注明出处: https://home.cnblogs.com/u/zhiyong-ITNote/ 整个asp.net core管道从WebHostBuilder到WebHost到后续请求的类中, ...
-
Asp.Net Core基于JWT认证的数据接口网关Demo
近日,应一位朋友的邀请写了个Asp.Net Core基于JWT认证的数据接口网关Demo.朋友自己开了个公司,接到的一个升级项目,客户要求用Aps.Net Core做数据网关服务且基于JWT认证实现对 ...
-
ASP.NET Core 使用 EF 框架查询数据 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 使用 EF 框架查询数据 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 使用 EF 框架查询数据 上一章节我们学习了如何设置 ...
-
ASP.NET Core 配置 EF 框架服务 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 配置 EF 框架服务 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 配置 EF 框架服务 上一章节中我们了解了 Entity ...
-
Spring MVC -- MVC设计模式(演示4个基于MVC框架的案例)
对于简单的Java Web项目,我们的项目仅仅包含几个jsp页面,由于项目比较小,我们通常可以通过链接方式进行jsp页面间的跳转. 但是如果是一个中型或者大型的项目,上面那种方式就会带来许多维护困难, ...
-
ASP.NET Core 基于JWT的认证(二)
ASP.NET Core 基于JWT的认证(二) 上一节我们对 Jwt 的一些基础知识进行了一个简单的介绍,这一节我们将详细的讲解,本次我们将详细的介绍一下 Jwt在 .Net Core 上的实际运用 ...
-
ASP.NET Core 基于JWT的认证(一)
ASP.NET Core 基于JWT的认证(一) Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计 ...
随机推荐
-
Golang 生成随机数
package main import ( "fmt" "math/rand" "time" ) func main() { rand.Se ...
-
maven配置远程仓库
1,当*仓库无法满足要求时,可能项目需要的构件存在另一个远程仓库中.可以在POM文件中配置该仓库.代码如下: <project> ...... <repositories> ...
-
redis 安装并设置为开机启动服务
安装 1.下载redis,wget http://download.redis.io/releases/redis-3.0.1.tar.gz 解压:tar zxvf redis3.0.1.tar.gz ...
-
4位bcd数转换为2进制数
DATA SEGMENTBUF DW 1234HBUF1 DW ? ;2进制数放到buf1内存单元DATA ENDSCODE SEGMENTASSUME CS:CODE ...
-
Android getReadableDatabase() 和 getWritableDatabase()
Android使用getWritableDatabase()和getReadableDatabase()方法都可以获取一个用于操作数据库的SQLiteDatabase实例.(getReadableDa ...
-
ZooKeeper安装、部署
一.简介 ZK的安装和配置十分简单,既可以配置成单机模式,也可以配置成集群模式,zk使用java编写的运行在java环境上,3个ZK服务进程是建议的最小进程数量,而且建议部署在不通的物理机 ...
-
CentOS6搭建OpenVPN服务器
一.服务器端安装及配置 服务器环境:干净的CentOS6.3 64位系统 内网IP:10.143.80.116 外网IP:203.195.xxx.xxx OpenVPN版本:OpenVPN 2.3.2 ...
-
WPF在在设计模式,使用动态样式
1.问题分析 WPF有时候要用到主题样式,比如颜色主题(红色.黄色之类的)通常是key相同,而value不同,比如会这么写: Background="{DynamicResource Bac ...
-
activemq之python使用stomp协议
参考链接: 安装:https://pypi.org/project/stomp.py/4.1.8/#history https://www.cnblogs.com/andylhc/p/9337945. ...
-
python 进程间通信(上)
一 使用queue来实现进程间的内存共享 #_*_coding:utf-8_*_ from multiprocessing import Process,Queue import os,time d ...