接下来就是跟资料库连结了,会着重说明 ASP.NET Core 跟 EF Core,如果有需要改画面才会说到 Blazor,这边会花比较多篇幅着墨。
首先要把 Blog 跟 Post 分开,我们先在NavMenu.razor
加入指向 Blog 的连结,接着将Blog.razor
改写,因为BlogId
必须有值且大於0才是一笔部落格资料,所以我们在BlogId
等於0时显示一个表单让使用者输入部落格名称,另外在BlogModel
的BlogName
加上Required
attribute,毕竟一个部落格要有名字。
不等於0的话则显示部落格名称及底下的日志,且部落格名称改用<h3>
元素。
12行有个参数OnValidSubmit="createBlog"
,代表的是如果表单验证通过,则执行指定的 function createBlog
,笔者先写好一个放在那里,等说完取资料的部分会再说明。
(注:如果希望触发OnValidSubmit
,必须有个type="submit"
的按钮,否则不管怎麽按都没效果)
有人问那如果BlogId
小於0呢?因为这个栏位是资料库由1开始递增产生,通常不会有这问题,除非有人窜改资料库,真的担心的话可以在资料库加入不可小於0的机制。
画面有了,接着来取资料,我们在根目录建立一个资料夹 Repository,建立一个介面 interface IBlogRepository
,Repository 里面再建立一个资料夹 Implement,建立一个类别 class BlogRepository
,资料夹结构因人而异,笔者是因为看到同事这样用,觉得可以快速找到介面跟实作很方便。
介面做的事情很简单,就是规范方法;实作的 13 到 18 行是依赖注入AppDbContext
;19 到 27行是取得第一笔 Blog,21行的 Include() 就是昨天说的不用自己 join table的方法,全名为Eager loading
,只要建表的时候有建好关联,就可以节省时间,其他还有Explicit loading
及Lazy loading
,都是 Entity Framework Core 提供的方便作法,如果是一对一的关联在 SQL 语法会被翻译成 Inner Join
,一对多则是 Left Join
。
正常来说 Blog 会跟登入者 (User) 绑定,可能有张 Table 记录BlogId
跟UserId
,但目前还没实作登入机制,所以就取第一笔资料,如果没有第一笔代表还没建立,回传空的 Blog;28 到 43行则是建立 Blog 的方法,30 到 31 行先检查 Blog 是否存在,不存在则建立 Blog,而不论是否存在,都回传型别为ResultViewModel
的物件,里面只有两个 Property:IsSuccess
、Message
,前端收到後是否要根据IsSuccess
做事,就是前端的事了。
接着去Startup.cs
注册刚才写的 Repository,有些人可能会问,上面的GuidService
跟之前建立的PostService
为什麽叫 Service 这边却叫 Repository,这是笔者的习惯,笔者此前开发的 Blazor 专案是多层式架构,分别为後端 API、中介 Model、前端 Blazor,後端处理资料的档案都以 Repository做为後缀词,前端取得资料的档案则以 Service 做为後缀词,端看不同公司的开发模式。後来笔者将 Service 抽成另一个专案,再後来又将 DbContext 抽成一个专案,都是为了方便日後有其他专案要参考 Model 或是只是要调动 Service 的话,不需要参考整个 Blazor 或是 API 专案。
最後就是BlogBase.razor.cs
了,16 到 17 行注入IBlogRepository
、IJSRuntime
,23 到 27 行改成非同步方法,因为取资料、存资料都用非同步,所以这边也要跟进;28到 31 行就是呼叫刚才写的GetBlog()
方法取得 Blog;32 到 43 行是这篇一开始说到的createBlog()
方法,这里如果成功的话就取得 Blog 资料,失败则用前面说过的JsInteropClasses
显示後端来的Message
。
接着让我们输入部落格名称,输入送出後,可以看到画面不同了,去看资料库,Blog 也能看到一笔资料。
前面说完 Blog,今天来说 Post 的部分,先建立IPostRepository
跟PostRepository
,里面只有CreatePost()
跟DeletePost()
两个方法,那怎麽没有取得单篇的GetPost()
或是多篇的GetPosts()
方法呢?因为 Blog 的GetBlog()
已经带入 Posts 所以不需要GetPosts()
,如果之後有需要看到个别日志的话,再建立GetPost()
。
(注:笔者参与的系统不多,也不知道这样的系统规划是否常见,只是因为一开始没有完整规划才会这样做。)
CreatePost()
如果在资料库找不到 Post 就新增一笔,找得到就修改,既然要修改就要有修改时间,所以我们在PostModel.cs
加上UpdateDateTime
栏位,用指令Add-Migration
新增一个 Migration 後下指令Update-Database
更新资料库,然後去Startup.cs
注册这个新建的 Repository。
(注:前面说过的内容笔者就不附图了,避免占版面。)
再来去PostBase.razor.cs
注入PostRepository
,改写一下deletePost()
,新增一个按下Submit
按钮会触发的事件createPost()
,PostBase.razor
加上前面加入的更新时间UpdateDateTime
、OnValidSubmit="createPost"
,Submit
按钮的type
改成submit
,让表格真的有送出功能。
接下来就是重头戏了,我们回到BlogBase.razor.cs
,把postId
删除,因为用不到了,add()
则改成传BlogId
跟CreateDateTime
到新的PostModel
,让这笔日志知道是跟着哪个 Blog。
产生CreateDateTime
跟UpdateDateTime
有两种选择:在前端或後端决定,端看系统如何规划,因为这边在 add 一笔 Post 的当下要避免看到0001-01-01 12:00:00
这样的尴尬时间,所以我们在前端给DateTime.Now
,至於後端要不要覆盖掉前端来的时间,就是规划问题了。
接着把PostModel.Content
的[MinLength]
改成50,因为不想打太多字XD。
打完内容後点击 Submit 按钮,我们的第一篇日志就建立成功了!
实际去看资料库,可以看到有资料,跟 BlogId 的关联也正确。
不过时间好像怪怪的,明明是晚上却显示早上时间,我们把Post.razor
的@bind:format
的小时格式改成大写H,画面的时间就正常了。
(注:因为这边的操作是以前学的,也忘记在哪里看的,就附上学习来源)
Ref: Blazor tutorial for beginners
Ref: Loading Related Data
<<: [Python 爬虫这样学,一定是大拇指拉!] DAY03 - 关於 Python (2)
>>: 【Day 03】从零开始的 Line Chatbot-建立专案
Email 安全 为什麽要收集各个企业的 Email 信箱,透过了解企业公开在外的 Email,可...
今天要来解APCS的题目,这次是105年10月29的实作题第二题,那我们就开始吧! 题目 解答 a=...
境外诈骗集团使用移动式机房的好处 移动式信号追踪难度高於一般固定位置信号 来电显示为台湾电信发号,降...
一页式网站 SPA SPA 全名 Single Page Applications 只有一个 HTM...
今天的实作内容主要根据教学网站进行。 将应用程序安装到Heroku 环境设定 Heroku主要利用四...