參考【ASP.NET Core跨平臺開發從入門到實戰 [張劍橋].pdf】從零搭建.net core項目(名稱叫NetNote),又踩了很多坑,趁着有印象記下:html
一、選用的是最簡單最空的項目,說是WebApplication,實際和控制檯同樣了,只有最基本的Starup.cs、Program.cs,以及幾個json,其它全沒有。這種最好,一個個往上搭,看須要什麼東西前端
二、看有些core源碼沒有再分一層數據層出來,直接在控制器搞定。我仍是按習慣把默認的改成NetNote.UI,再建一個類庫,叫NetNote.DAL數據庫
一下沒注意,選類庫的時候,仍是選了上面的.net Standard,結果代碼都寫好了,發現是不能CodeFirst仍是什麼的,總之提示不是core項目,報錯。仔細一看,原來新建項目時下面還有專門的.net core 類庫。json
再建個core類庫,把代碼剪切過來,把舊的刪了,再改文件夾名稱、改解決方案裏文件夾名稱,正常了瀏覽器
三、照着教程先來DAL層,要裝Framework.Core.SQLServer、Framework.Core.Tools,好久以前(去年?前年?)還據說ef core支持很差,如今應該很成熟了app
四、照着把DAL層的實體類、接口、接口實現倉儲建好,要在UI層配置,教程裏都建了接口,平時工做都沒先定義接口再作增刪改查,致使叫法不統一,好比有的叫Update,有的叫Save,但也不是很影響就是了,都有代碼提示。框架
五、坑都在這裏踩了,重點說一下異步
public void ConfigureServices(IServiceCollection services) { string connection = @"Server=.;Database=Note;UID=sa;PWD=XXX;"; services.AddDbContext<NoteContext>(options => options.UseSqlServer(connection)); services.AddScoped<INoteRepository, NoteRepository>(); services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //app.Run(async (context) => //{ // await context.Response.WriteAsync("Hello World!"); //}); app.UseMvcWithDefaultRoute(); }
倉儲層建好後要在ConfigureServices配置async
一開始MVC不識別,即瀏覽器訪問不了(由於是徹底空的項目),要配置services.AddMvc(),並在Configure裏配置默認路由。這個弄了半天,覺得都底層默認支持原始路由。post
MVC配置後仍沒法用,全部頁面均爲Hello World,原來是初始代碼裏有這麼一句(上面註釋了的),全部輸出均爲Hello World了
六、好不容易UI層弄好了,要CodeFirst生成數據庫,死活不行,一開始說要裝Core Tools,還有個什麼東西忘了,由於我是空項目一個個往裏裝所需插件的。裝完後仍是不行,最後用Package Manager又能夠了
會多一個這樣的文件夾出來,查網上資料好像也是說若是要直接用dotnet ef遷移,要提早把這個遷移文件夾及內容配好。用PM的會幫咱們配
平時都是DBFirst,沒用過CodeFirst,恰好嘗試下
七、總體項目文件夾以下:
教程是另弄了個ViewModel來和實體對應,JAVA也基本是這樣,在數據庫實體以外再弄一個VO來對應。我一直以爲很麻煩、不必。
若是字段有所不一樣還好,若是是徹底同樣的,何須這樣再來一遍?退一步說真要這樣弄個實體,好歹也用反射什麼的自動賦值吧
這個以前有和水平較高的大佬討論過,也網上看過,說是爲了避免暴露數據庫內部結構,那若是不想暴露,好歹ViewModel要取徹底不一樣的纔有意義吧,並且數據庫字段名給別人知道了也沒什麼特別要緊。
還有種說法是爲了避免因數據庫結構而改變前端什麼的,也不對啊,數據庫若是變了,前端模型也得跟着變,代碼也得跟着變,都是要一條龍的
這個可能就和先接口再實現同樣吧,是一種規範,大項目要這樣約束好,平時小項目感受是沒關係,既不要接口,也不要對應UI實體類,節省時間,也不會帶來什麼後遺症
八、順便說下,core都是用這種異步寫法了,雖然說小項目也是效率看不出來,但養成習慣就好,畢竟是底層更高效的,寫了也不吃虧
主要是方法上用asyn Task,內部代碼用await,其它沒什麼區別
public async Task<IActionResult> Index() { List<Note> notes = await noteRepository.ListAsync(); return View(notes); }
九、控制器上都這樣用注入了,原先公司用的是在Base裏用單例工廠,感受是同樣用,就是不用實例化就能調後臺唄,不是一回事?
private INoteRepository noteRepository; public NoteController(INoteRepository diNoteRepository) { noteRepository = diNoteRepository; }
公司目前是這樣,單例的工廠提早備好服務,哪裏要用直接用就能夠,也是無需再實例化,這個單例和注入的區別,還要再研究下基礎知識才行
public class BaseController : Controller {protected EntityRepositoryService ucEntity = UserCenterFactory.EntityRepositoryService; protected SqlRepositoryService ucSql = UserCenterFactory.SqlRepositoryService;
=================
十、TagHelpers的坑。。。照着教程用 <a asp-action="Add">添加Note</a> ,但解析出來,竟然就是原本來本的 <a asp-action="Add">添加Note</a> 這種html,爲何不翻譯成a標籤的href之類的呢?
找了半天,原來仍是由於新建的是空項目的緣由,默認會自帶個_ViewImports.cshtml,裏面就一句話
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
手動在視圖頁面上面加了這個就行了
十一、還有個坑,教程上漏寫了一個普通視圖的控制器入口,我還覺得框架底層又有什麼新寫法,直接兼容頁面和提交呢(或仍是我哪裏沒配對?)
public IActionResult Add() { return View(); } [HttpPost] public async Task<IActionResult> Add(NoteModel nmModel) { if (!ModelState.IsValid) { return BadRequest(ModelState); } await noteRepository.AddAsync(new Note { Title = nmModel.Title, Content = nmModel.Content, Create = DateTime.Now }); return RedirectToAction("Index"); }
教程裏面是沒有上面普通的public IActionResult Add(){return View()} 的,只有下面post的保存方法,我就看了半天,那Add頁面是怎麼展現的呢?原先只有接收post啊。
也不知是真支持這樣寫,但須要另外配(或框架哪裏有處理),仍是真漏了,反正我加上普通的方法讓它返回到頁面就能夠了
十二、外鍵
平時EF從沒用過外鍵,不方便,網上也建議不要用外鍵,數據庫只作好存儲的事,不要搭上業務。
教程裏這樣寫,試了會報錯,建表是會自動建外鍵,但新增時,只增了一張表,另張表沒處理,是外鍵會自動處理?感受是須要手動加一句吧,兩張表都要保存,否則外鍵的那張表怎麼知道要存什麼數據。
去掉了外鍵,單表保存正常,這本教程感受源碼直接拿來上機會有些問題,恰好在排查問題時能加深理解