# 最簡單的CURD
對于任何一個WEB應用來說,CRUD都是基礎中的基礎,雖說每本書上都會說,但是對于Asp.Net Core來說,還是有一些值得注意的點。
> CRUD: create, read, update, delete的首字母縮寫
本文對應[Demo](https://github.com/panfengstudio/workshop/tree/2018/05/05)。
## EntityFramework Core
Doc: [EF Core](https://docs.microsoft.com/zh-cn/ef/core/)
EF Core隨著.net core的版本更新,現在也是到了2.0版本,坑也少了不少。根據張隊最近的[調查報告](https://mp.weixin.qq.com/s?__biz=MzAwNTMxMzg1MA==&mid=2654070376&idx=1&sn=cf613167592f9955dd5b76424a430dc6)來看,EF Core的使用率也不低。
當然,作為一個沒寫過大型項目的新人,沒資格去討論什么性能、優化之類,只能說EF Core對小型的WEB應用,以及新人上手還是非常友好的,僅需通過簡單的配置,就可以像使用內存中對象一樣操縱數據庫。
查詢
```cs
// 使用基于Method的LINQ
var records = _context.Records
.Where(record => record.SignInTime >= begin && record.SignInTime <= end)
.Select(record => new
{
StudentId = record.StudentId,
Name = record.Name,
SignInTime = record.SignInTime,
SignOutTime = record.SignOutTime
}).ToList();
// 使用基于Query的LINQ
Record record = (from r in _context.Records
where r.StudentId == model.StudentId
&& r.SignOutTime == null
select r).FirstOrDefault();
```
寫入
```cs
// 根據模型數據創建記錄
Record record = new Record
{
StudentId = model.StudentId,
Name = model.Name,
SignInTime = DateTime.Now
};
// 向上下文中添加記錄,并保存
_context.Add(record);
_context.SaveChanges();
```
修改
```cs
// 記錄簽到時間并保存
record.SignOutTime = DateTime.Now;
_context.Update(record);
_context.SaveChanges();
```
可以看到在這些簡單的例子中,每次修改上下文后,都需要`SaveChanges`才能將修改保存到數據庫,對上下文的修改僅是保存一個標記。
## 依賴注入
Doc: [依賴注入](https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/dependency-injection)(DI)
這應該是Asp.Net Core中最顯著的特征了,所有的依賴都是通過IOC框架來提供,同時微軟也在Asp.Net Core中提供了一個夠用的官方IoC框架。
微軟的推薦實踐是在StartUp.cs的ConfigureServices中添加相關依賴。
```cs
public void ConfigureServices(IServiceCollection services)
{
// 添加內存數據庫
services.AddDbContext<RecordDbContext>(options =>
options.UseInMemoryDatabase("WorkShopDev"));
// 添加MVC服務
services.AddMvc();
}
```
然后,通過構造函數注入。(當然,在有需要時,也可以在對應函數中注入)
```cs
public RecordController(RecordDbContext context)
{
_context = context;
}
```
## 模型綁定
Doc: [模型綁定](https://docs.microsoft.com/zh-cn/aspnet/core/mvc/models/model-binding)(Model Binding)
Asp.Net Core會用一種Magic的方法去匹配你所需要的對應參數,分別從以下幾個數據源(優先級從上到下):
1. Form values:這些是使用 POST 方法進入 HTTP 請求的窗體值。 (包括 jQuery POST 請求)。
2. Route values:路由提供的路由值集。
3. Query strings:URI 的查詢字符串部分。
如有需要,你還可以用類似`[FromForm]`這樣的特性去指定某一參數的來源。
值得注意的是`[FromBody]`,由于Body在Request中是作為Stream存在的,所以只能讀取一次,也就是說每個Action中至多只能出現一個`[FromBody]`。
> 當你的Header為`application/json`時,就需要用`[FromBody]`來綁定參數,例如微信小程序。