Asp.net Core基于MVC框架实现PostgreSQL操作
簡單介紹
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
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
開始
新建項目,選擇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上傳到服務器,然后參照前文發布。
前文:http://blog.csdn.net/lanwilliam/article/details/51880124
總結:
????Asp.net Core 目前來說功能性還不完善,暫時不建議大型應用往上遷移,但是如果是小型項目,比較簡單,可以在仔細論證后嘗試使用。注意仔細論證,因為目前.net core并不是所有類庫都能夠實現跨平臺。簡單來說,System.Drawing就無法使用,所以后臺畫水印就需要其他三方庫,這個請自行仔細論證。不過小項目發布到linux虛擬機上面,確實可以省一筆錢。
原文地址:http://www.cnblogs.com/lanwilliam/p/5663931.html
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注
總結
以上是生活随笔為你收集整理的Asp.net Core基于MVC框架实现PostgreSQL操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Entity Framework Cor
- 下一篇: 大数据项目实践:基于hadoop+spa