Blog專案 - 連接DB
2020-09-15 23:11 Last Edited: 2020-09-15 23:12 1,119

目前的進度
首頁文章列表 (Controller & View)
內文
連接DB

閱讀文章的基本功能已經大致完成,但還沒有文章,所以現在開始著手寫連接DB的部份
前文提到當我們request /blog或者/blog/{id} 時,會執行BlogFactory的2個Method,從database裡面抓取Blog數據,傳給Views

public class BlogController : Controller
{
    public IActionResult Index()
    {
        List<Models.Blog> blogs = BlogFactory.GetBlogsByPage(1);
        ViewData["Title"] = "";
        return View(blogs);
    }
    [Route("/blog/{id:int}")]
    public IActionResult Individual(int id)
    {
        ViewData["BlogId"] = id;
        List<Models.Blog> blogs = BlogFactory.GetBlog(id);
        if (blogs.Count > 0)
        {
            ViewData["Title"] = blogs[0].Title;
            return View("Detail", blogs[0]);
        }
        else
        {
            return Redirect("~/");
        }
    }
}

以下是BlogFactory內容

using Dapper;
namespace Blog.Models
{
public static class BlogFactory
    {
        static ExternalJsonConfigReader configReader = new ExternalJsonConfigReader(@"C:Configconfig.json");
        static string blogConnStr = configReader.GetValue("BlogConnStr");
        static int blogPerPage = 10;

        public static List<Blog> GetBlogs()
        {
            using (var connection = new SqlConnection(blogConnStr))
            {
                return connection.Query<Blog>("select * from GetVisibleBlogs() order by id desc").ToList();
            }
        }
        /// <summary>
        /// using int as parameter can avoid sql injection too. how brilliant me!
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static List<Blog> GetBlog(int id)
        {
            using (var connection = new SqlConnection(blogConnStr))
            {
                return connection.Query<Blog>($"select * from GetVisibleBlogs() where id=@id", new { id = id }).ToList();
            }
        }
        public static BlogIdPair GetBlogNextBlog(int id)
        {
            try
            {
                using (var connection = new SqlConnection(blogConnStr))
                {
                    return connection.QuerySingle<BlogIdPair>($"select * from GetBlogNextBlog(@id)", new { id = id });
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        public static BlogIdPair GetBlogPrevBlog(int id)
        {
            try
            {
                using (var connection = new SqlConnection(blogConnStr))
                {
                    return connection.QuerySingle<BlogIdPair>($"select * from GetBlogPrevBlog(@id)", new { id = id });
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }
    }
}

目前先提供4個method,分別是供首頁用的GetBlogs()、內文用的GetBlog(int id)、和導航的GetBlogNextBlog()和GetBlogPrevBlog()

當我們要連接Database時,首先要建立一個SqlConnection,傳一個connectionString進去,這個connectionString就是database的登入資訊,包含有db的hostname、port、登入方式、帳密等,不同資料庫會有不同的寫法,我家在用的主要是微軟sql server的Community版 - sql express,它的connection string長這樣:

"Data Source={ip或者hostname};Initial Catalog={db名稱};Persist Security Info=True;User ID=帳號帳號;Password=密碼密碼"

 如果你資料庫就建在本機,而且是用windows的話,可以直接用windows目前使用者登入,不用填帳密就不怕被人偷看到

"Data Source=127.0.0.1;Initial Catalog={DB名稱};Integrated Security=True"

和DB connect後就可以開始用這個connection操作DB

using (var connection = new SqlConnection(blogConnStr))
{
    return connection.Query<Blog>("select * from GetVisibleBlogs() order by id desc").ToList();
}

SqlConnection.Query()這個method讓用家執行裡面的Sql Query,比如select * from table那些,它會傳回一個IEnumerable<dynamic>,裡面裝著Query的結果。connection.Query<Blog>這裡則是dapper提供的generic type方法,Dapper會自動從傳回的結果中對比Blog物件的屬性,如果名字和datatype都符合,就自動填入Blog物件中。

    public IActionResult Index()
    {
        List<Models.Blog> blogs = BlogFactory.GetBlogsByPage(1);
        ViewData["Title"] = "";
        return View(blogs);
    }

 

@model Blog
@model IEnumerable<Blog>

還記得Views/Blog/index.cshtml和Views/Blog/Detail.cshtml的第一行分別是以上這兩句嗎?
@model表示這個View能接受什麼類型的object作parameter
除了使用@model之外,也可以填寫ViewData這個Dictionary<string, object> (或者ViewBag)來傳送資料進去View
兩者的分別在於model是強型別,ViewData則沒規定,可以亂來,但這屬於anti-pattern,盡量不用。

當拿到List<Blog>後,就填入Views中再return,request就能收到它產生的html網頁內容。

Category: Coding
Tags: Side Project