Web API 之CRUD
注:例子来自微软Web API官网(https://www.asp.net/web-api/overview/data/using-web-api-with-entity-framework/part-1),也有加入自己的一点体会。
一、创建一个MVC项目,选择Web API类型的MVC,命名为BookService:
二、创建Mode和Controller:
在Models文件夹下面创建两个Model,分别是Author.cs和Book.cs;
1)、其中Author的定义如下:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; namespace BookService.Models
{
public class Author
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
}
2)、Book的定义如下:
using System.ComponentModel.DataAnnotations; namespace BookService.Models
{
public class Book
{
public int Id { get; set; }
[Required]
public string Title { get; set; }
public int Year { get; set; }
public decimal Price { get; set; }
public string Genre { get; set; } // Foreign Key
public int AuthorId { get; set; }
// Navigation property
public Author Author { get; set; }
}
}
3)、插入小知识点----POCO:
(1)、概念:所谓的POCO就是 pure old C# object 的缩写,翻译过来就是“纯洁老式的C#对象”,不过太拗口了,所以现在更多的称它为“简单C#对象”。
含义:POCO的内在含义是指一个类不曾继承或者实现任何类和接口,也没有被其它框架侵入的C#对象。就是最原生态的C#对象,我的理解是它是一个“光棍”。
(2)、意义:简单、灵活、易扩展。我们定义的POCO在后面使用的用于逻辑层的DTO(Data Transfer Object)以及用于UI显示的VO(View Object)都是以此为基础的。
三、添加API Controller,在控制器的选择当中选择 “包含操作的Web API(使用EF)”,这样子它会帮我们生成增删改查的操作。
选择之后会蹦出如下弹出框要求对控制器进行设置:
设置的话就按照上面要求的来做就行。下面进行解释:
A、模型类的选择:下拉选择,是为哪一个Model创建控制器就选择哪一个;
B、数据上下文,这个是用来创建Context文件的,这个文件是Model与数据库交互的一个门户,是对数据操作的一个集合,所有的Model都在这个类里面进行管理,我理解成是中介。添加的方式就是点击右侧的“+”然后再弹出框中点击确定就OK了。就是选择默认的名字就好了。
C、 选择异步的控制器操作,异步操作方法通常用于长时间运行的、非 CPU 绑定的请求操作方法,在这个小例子当中实际上并不是必须的。(我对这个其实还不懂,今后会好好去搞明白,索性这个异步在目前对于例子也不重要,所以可以先不用管)
D、控制器名称,这个建议是使用默认的,这个命名是很规范的,使用了REST API的设计原则,对于资源命名使用的是名词,而且是复数形式Books而不是单数形式Book,很规范。
点击 “添加” 之后会生成两个文件BooksController.cs控制器(在controller文件夹中)和BookServiceContext.cs上下文文件(在Models文件夹中)。
注:如果是跟着上面的步骤做的话其实是无法创建控制器的,因为EF是ORM框架,是根据反射进行创建的,也就是说它是需要程序集的,因此在创建使用EF的控制器之前需要进行编译,之后才可以创建成功。在这里才进行说明是个人觉得犯错才记得牢(*_*).
BooksController.cs文件主要包含对Book.cs实体类的CRUD操作,而BookServiceContext.cs包含了对Book.cs实体的注册。打开的话就可以看到。
接下来该做的就是按照上面的步骤创建Author.cs实体的控制器。
三、创建数据库,完成EF的映射:
1、添加Migration:生成一下-->在VS中选择工具-->NuGet包管理器-->Nuget程序管理控制台--->输入命令:Enable-Migrations
效果: 在项目之下创建一个文件夹Migration,里面有一个配置文件Configuration.cs。
2.打开Configuration.cs文件,添加代码(用途是初始化数据库当中的数据),代码如下:
protected override void Seed(BookService.Models.BookServiceContext context)
{
context.Authors.AddOrUpdate(x => x.Id,
new Author() { Id = , Name = "Jane Austen" },
new Author() { Id = , Name = "Charles Dickens" },
new Author() { Id = , Name = "Miguel de Cervantes" }
); context.Books.AddOrUpdate(x => x.Id,
new Book() { Id = , Title = "Pride and Prejudice", Year = , AuthorId = ,
Price = 9.99M, Genre = "Comedy of manners" },
new Book() { Id = , Title = "Northanger Abbey", Year = , AuthorId = ,
Price = 12.95M, Genre = "Gothic parody" },
new Book() { Id = , Title = "David Copperfield", Year = , AuthorId = ,
Price = , Genre = "Bildungsroman" },
new Book() { Id = , Title = "Don Quixote", Year = , AuthorId = ,
Price = 8.95M, Genre = "Picaresque" }
);
}
seed方法是用于为数据库设置初始值的,一般在开发项目的时候我们不使用这个方法,这个例子只是为了为数据库添加数据才使用的。
3、继续在Nuget程序包控制台输入指令:
Add-Migration Initial
Update-Database
分析:
Add-Migration Initial:生成文件; Update-Database:这个方法会创建数据库,当Model改动的时候,需要再次运行上面两个指令进行数据库的更新操作(可以想见,这个就是使用了Migration的好处:不需要再
重新创
建EF,不会丢失数据)。
注:在这一步的时候我出了一个错误:根本无法创建数据库成功,后来找到原因,因为我使用的是VS自带的LocalDB,生成的实例名是Data Source=(localdb)\MSSQLLocalDB
(在web.config中),这个实例名是SQL Express2014的,而我安装的是SQl Express 2012,这样子的话就会出现问题,需要把实例名改成Data Source=(localdb)\v11.0,
那么问题就解决了。个人感觉这是一个问题,微软的VS无法检测到我们安装的是哪一个版本的SQL Exepress. 让我们来看看数据库:
4、创建DTO(Data Transfer Object):
先来说说DTO的优点:
1)、克服对数据库的重复调用;
2)、隐藏不想让用户知道的数据库表规则,即隐藏一些字段,防止数据库规则泄露;
3)、减少一些属性(字段)的调用降低服务器负荷;
4)、减少数据库中表的对象嵌套,即方便用户使用数据;
5)、避免over posting(不懂这个怎么翻译呀);
6)、解耦合(数据层和业务逻辑层之间解耦)。 四、修改自动生成的BooksController中的GetBooks()、GetBook(int id)和PostBook()方法。
// GET api/Books
public IQueryable<BookDTO> GetBooks()
{
var books = from b in db.Books
select new BookDTO()
{
Id = b.Id,
Title = b.Title,
AuthorName = b.Author.Name
}; return books;
} // GET api/Books/5
[ResponseType(typeof(BookDetailDTO))]
public async Task<IHttpActionResult> GetBook(int id)
{
var book = await db.Books.Include(b => b.Author).Select(b =>
new BookDetailDTO()
{
Id = b.Id,
Title = b.Title,
Year = b.Year,
Price = b.Price,
AuthorName = b.Author.Name,
Genre = b.Genre
}).SingleOrDefaultAsync(b => b.Id == id);
if (book == null)
{
return NotFound();
} return Ok(book);
} [ResponseType(typeof(Book))]
public async Task<IHttpActionResult> PostBook(Book book)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} db.Books.Add(book);
await db.SaveChangesAsync(); // New code:
// Load author name
db.Entry(book).Reference(x => x.Author).Load(); var dto = new BookDTO()
{
Id = book.Id,
Title = book.Title,
AuthorName = book.Author.Name
}; return CreatedAtRoute("DefaultApi", new { id = book.Id }, dto);
}
五、创建UI和写Script脚本,显示数据:
注:这一步和官网的是不一样的,如果看官想看的话可以自行到官网查看:https://www.asp.net/web-api/overview/data/using-web-api-with-entity-framework/part-6
官网使用的是Knockout.js。公司这边已经不使用Knockout.js,所以我是使用angular.js来写的。
1、先上HTML代码,把View文件夹下的子文件夹下面的Home中的index替换成如下代码(要自己引用angular.js):
<style type="text/css">
h1,h2,h3,html,div{
margin:0;
padding:0; }
#books {
border: 2px solid #000000;
padding: 20px;
width: 350px;
font-size: 18px;
margin:10px;
float:left;
}
#addBlock{
border: 2px solid #000000;
padding: 20px;
width: 350px;
font-size: 18px;
margin:10px;
float:left;
} #details{
border: 2px solid #000000;
padding: 20px;
width: 350px;
font-size: 18px;
margin:10px;
float:left;
}
#edit{
border: 2px solid #000000;
padding: 20px;
width: 350px;
font-size: 18px;
margin:10px;
clear:both;
}
/*div{float:left;
margin:20px;
}*/
</style> <div ng-app="First" ng-controller="firstController"> <!--base message-->
<div id="books">
<h1>Books</h1>
<p ng-repeat="x in baseMessage"> <label ng-bind="x.Title+': '+x.AuthorName"></label>
<a href="#" ng-click="detail(x.Id)">Details</a>
<a href="#" ng-click="delete(x.Id)">Delete</a>
</p>
</div> <!--detail message-->
<div id="details">
<h1>Details</h1>
<label>Author</label> <label>{{": "+Author}}</label><br />
<label>Title</label> <label>{{": "+Title}}</label><br />
<label>Year</label> <label>{{": "+Year}}</label><br />
<label>Genre</label> <label>{{": "+Genre}}</label><br />
<label>Price</label> <label>{{": "+Price}}</label><br />
</div>
<!--add block-->
<div id="addBlock">
<h1>Add Book</h1>
<label>Author</label><select id="Author" ng-options="item as item.AuthorName for item in baseMessage" ng-model="selectedAuthor"></select><br />
@*@Html.DropDownList("Author", new List<SelectListItem>(), new { ng_options = "item as item.AuthorName for item in baseMessage", ng_model = "selected" });*@
<!--Why???????-->
<label>Title</label><input type="text" id="Title" /> <br />
<label>Year</label> <input type="text" id="Year" /><br />
<label>Genre</label> <input type="text" id="Genre" /><br />
<label>Price</label> <input type="text" id="Price" /><br />
<input type="button" value="Add" ng-click="AddBook(selectedAuthor)"/>
</div>
<hr />
<!--Edit block-->
<div id="edit">
<h1>Modify Books</h1>
<label>Book:</label><select id="Author" ng-options="item as item.Title for item in baseMessage" ng-model="selectedBook"></select><br />
<label>Title:</label><input type="text" id="titleModify" /> <br />
<label>Year:</label> <input type="text" id="yearModify" /><br />
<label>Genre:</label> <input type="text" id="genreModify" /><br />
<label>Price:</label> <input type="text" id="priceModify" /><br />
<input type="button" value="Modify" ng-click="ModifyBook(selectedBook)" />
</div>
</div>
2、新建一个js文件,引用到index,js文件写的是angular代码,如下:
var app = angular.module("First", []);
app.controller("firstController", function ($scope, $http) {
var message = new Array();
var selectAuthor = new Array();
$http({
method: "GET",
url: "/api/Books/"
}).then(function (data) {
angular.forEach(data.data, function (value, key) {
message.push(value);
selectAuthor.push(value.AuthorName);
})
$scope.baseMessage = message;
$scope.selectAuthors = selectAuthor;
$scope.selected = $scope.baseMessage[0];
}) $scope.detail = function detail(id) {
$http.get("/api/Books/" + id).then(function (data) {
$scope.Author = data.data.AuthorName;
$scope.Title = data.data.Title;
$scope.Year = data.data.Year;
$scope.Genre = data.data.Genre;
$scope.Price = data.data.Price;
});
} $scope.delete = function (id) {
$http.delete("api/Books/" + id).then(function () {
alert("OK,You have already delete it!");
})
} $scope.AddBook = function (selectedAuthor) {
//alert(selected.Id);
var Title = $("#Title").val();
var Year = $("#Year").val();
var Genre = $("#Genre").val();
var Price = $("#Price").val();
var book = {
AuthorId: parseInt(selectedAuthor.Id),
Title: Title,
Year: parseInt(Year),
Genre: Genre,
Price: Price
}
$http.post(
"/api/Books/", book).success(function () {
alert("Add Sucess!");
})
} $scope.ModifyBook = function (selectedModify) {
var id = selectedModify.Id;
var AuthorId = 1;
authorId(id);
function authorId(id) {
$http.get("/api/Books/" + id).then(function (data) {
AuthorId = data.data.AuthorId; var Title = $("#titleModify").val();
var Year = $("#yearModify").val();
var Genre = $("#genreModify").val();
var Price = $("#priceModify").val();
var book = {
AuthorId: AuthorId,
Id: parseInt(selectedModify.Id),
Title: Title,
Year: parseInt(Year),
Genre: Genre,
Price: Price
}
//$http.put("/api/Books/" + selectedModify.Id, book,function () {
// alert("OK,You have already modify it (*_*) ~");
//});
$http({ method: "PUT", url: "/api/Books/" + selectedModify.Id, data: { "id": selectedModify.Id, "book": book } }).then(function () {
alert("OK,You have already modify it (*_*) ~");
}); });
}
}
});
3、生成解决方案然后运行就会有结果了。
注:博主有强迫症,一个博文不喜欢写太长,所以对于angular代码的解析就放在其他博文里面http://www.cnblogs.com/heisehenbai/p/Angular.html
Web API 之CRUD的更多相关文章
- Asp.Net Web API 2(CRUD操作)第二课
Asp.Net Web API 2(CRUD操作)第二课 Asp.Net Web API 导航 Asp.Net Web API第一课:入门http://www.cnblogs.com/aehyok ...
- ASP.NET Web API 基本操作(CRUD)
上一篇介绍了ASP.NET Web API的基本知识和原理,这一篇我们通过一个更直观的实例,对产品进行CRUD操作(Create/Read/Update/Delete)来继续了解一下它的基本应用. 创 ...
- ASP.NET Core Web API Cassandra CRUD 操作
在本文中,我们将创建一个简单的 Web API 来实现对一个 “todo” 列表的 CRUD 操作,使用 Apache Cassandra 来存储数据,在这里不会创建 UI ,Web API 的测试将 ...
- 在ASP dot Net Core MVC中用Controllers调用你的Asp dotnet Core Web API 实现CRUD到远程数据库中,构建你的分布式应用(附Git地址)
本文所有的东西都是在dot Net Core 1.1环境+VS2017保证测试通过. 本文接着上次文章接着写的,不了解上篇文章的可能看着有点吃力.我尽量让大家都能看懂.这是上篇文章的连接http:// ...
- 在Core环境下用WebRequest连接上远程的web Api 实现数据的简单CRUD(续)
这篇博客是上篇博客的续写,上篇博客用的是HttpClient取远程数据,用WebRequest提交,更新,删除数据.上篇本来想全文都用httpClient,可是当时无论如何也实现不了数据的提交,于是换 ...
- ASP。NET Core Blazor CRUD使用实体框架和Web API
下载source code - 1.7 MB 介绍 *请查看我的Youtube视频链接来学习ASP.NET Core Blazor CRUD使用实体框架和Web API. 在本文中,我们将了解如何为A ...
- 【ASP.NET Web API教程】2.3 与实体框架一起使用Web API
原文:[ASP.NET Web API教程]2.3 与实体框架一起使用Web API 2.3 Using Web API with Entity Framework 2.3 与实体框架一起使用Web ...
- 返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API
原文:返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API [索引页][源码下载] 返璞归真 asp.net mvc (10) - asp.net ...
- 通过HttpClient 调用ASP.NET Web API
在前面两篇文章中我们介绍了ASP.NET Web API的基本知识和原理,并且通过简单的实例了解了它的基本(CRUD)操作.我们是通过JQuery和Ajax对Web API进行数据操作.这一篇我们来介 ...
随机推荐
- 设计模式--组合模式Composite(结构型)
一.概念 组合模式允许你将对象组合成树形结构来表现"整体/部分"层次结构.组合能让客户以一致的方式处理个别对象以及对象组合. 二.UML图 1.Component(对象接口),定义 ...
- shell:遍历目录和子目录的所有文件
#!/bin/bash function getdir(){ ` do dir_or_file=$"/"$element if [ -d $dir_or_file ] then g ...
- web项目中各种路径的获取
以工程名为/DemoWeb为例: 访问的jsp为:http://localhost:8080/DemoWeb/test/index.jsp 1 JSP中获得当前应用的相对路径和绝对路径 (1)得到工程 ...
- Java获取用户ip
/** * 获取客户端ip地址(可以穿透代理) * * @param request * @return */ public static String getRemoteAddr(HttpServl ...
- sql 数据库结构导出到文件
SELECT 表名 = Case When A.colorder= Then D.name Else '' End, 表说明 = Case When A.colorder= Then isnull(F ...
- CentOS7 编译安装 nginx-1.10.0
对于NGINX 支持epoll模型 epoll模型的优点 定义: epoll是Linux内核为处理大批句柄而作改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著的 ...
- CSS 清除默认样式
通常有以下几句就够了: *{margin:0;padding:0} li{list-style:none} img{vertical-align:top;border:none} 如果你想写全也可以: ...
- MFC 滑动条的重绘
MFC自带的滑动条的样子是这样的. 比较难看,所以需要重绘下,重绘后的样子是这样的. 代码如下: CustomSliderCtr.h #pragma once // CCustomSliderCtr ...
- Jquery知识点
Jquery $代表选择器 JS 选取元素 操作内容 操作属性 操作样式 <div id="aa" style="width:100px; height:100px ...
- myeclipse maven 安装
myeclipse 上安装 Maven3 环境准备: JDK 1.6.45 Maven 3.0.5 myeclipse 8.5 安装 Maven 之前要求先确定你的 JDK 已经安装配置完成.Ma ...