Asp.net Core最大的價值在於跨平臺、跨平臺、跨平臺。重要的事情說三遍。可是目前畢竟是在開發初期,雖然推出了1.0.0 正式版,可是其實好多功能尚未完善。比方說編譯時的一些文件編碼問題,輔助工具Tools的一些Bug,還有一些好用的模板和平臺實現還沒有完成等一些問題。但這畢竟是一個好的開始,而且在Github上,你們都還在積極的完善,你也能夠參與進來。地址:https://github.com/aspnet html
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月,支持狀況以下: mysql
Database Providers jquery
The following providers are available linux
因此提供給咱們選擇的數據庫仍是有限的(主要是不支持MySql,Devart這東西筆者不瞭解,不評論)。總得來講,對MS SQL Server的支持確定是最好的,因此場景容許下,首選Sql server。其次,就DB2和PostgreSQL可選了。筆者不喜歡DB2(不少緣由,主要是開發操做管理麻煩,並不是說DB2自己存在問題),PostgreSQL其實也不太好用,不過誰叫他免費呢,確定是好多國內公司首選。 git
PostgreSQL自己歷史悠久,記得好像上世紀80年代就存在了,免費開源,並且是有專門社區維護。設計理念是以健壯性爲首選,因此收到光打企業級平臺歡迎。關於PostgreSQL和MySQL之間的優缺點,這個其實不太好說,MySQL在損失健壯性的同時,提升了性能,而且支持不少非標準新特性,而PostgreSQL在健壯性上,號稱不弱於Oracle,性能優秀,徹底支持SQL標準,因此其實並不差。 github
Ubuntu Server(16.04)虛擬機1臺,IP:192.168.1.6 預裝了PostgreSQL數據庫,並配置好防火牆,ssh鏈接等基礎環境。確保可以外部訪問。 ajax
VS2015 Update3 sql
Putty 和SSH Secure File Transfer Client chrome
參考以前的博客:http://blog.csdn.net/lanwilliam/article/details/51880124 數據庫
這裏要說一下,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的引用,是從示例項目中搬來的。
這裏要說明一下,微軟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類進行管理。
模板已經提示給你,須要修改這部分代碼,實現動態配置鏈接的目的。
進行以下修改:
註釋掉OnConfiguring方法,增長構造函數,咱們把註冊放到Startup中去完成。
打開appsetting.json文件,增長以下配置:
其實這就至關於原來asp.net中的Web.config中的ConnectionStrings。
打開StartUP.cs 文件,找到ConfigureServices方法,添加選中代碼:
到這裏就看明白了吧,註冊DBContext,使用Npgsql,並給出數據庫鏈接字符串。
在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方法中執行。這樣處理可以極大的提升服務器的併發性能,具體請自行學習。
增長對應的頁面以下:
@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>
@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");}
}
@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>
@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>
@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");}
}
<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>
增長如上兩個鏈接。Blog的添加參考TbUser。這裏主要是想讓你們看出來DBContext的用法,因此特地弄了兩個實體類。
這裏沒有改默認的頁面。
再看咱們加的頁面。
而且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; }
將WebApp項目發佈出來,使用SSH Secure File Transfer上傳到服務器,而後參照前文發佈。
Asp.net Core 目前來講功能性還不完善,暫時不建議大型應用往上遷移,可是若是是小型項目,比較簡單,能夠在仔細論證後嘗試使用。注意仔細論證,由於目前.net core並非全部類庫都可以實現跨平臺。簡單來講,System.Drawing就沒法使用,因此後臺畫水印就須要其餘三方庫,這個請自行仔細論證。不太小項目發佈到linux虛擬機上面,確實能夠省一筆錢。