Tại sao cần unitofwork trong mvc c

[ PHẦN 1: XÂY DỰNG GIAO DIỆN WEBSITE VỚI HTML5, CSS3,JAVASCRIPT, JQUERY ]

Thời lượng:  14  buổi

BUỔI 1: Tìm hiểu HTML5 và hệ thống thẻ HTML5

BUỔI 2: Định dạng giao diện bằng CSS3, bố cục trang web với thẻ HTML5 và CSS3

BUỔI 3: String và String buider, mảng dữ liệu, các thao tác với mảng

BUỔI 4: Tìm hiểu về Web Responsive và framework Bootstrap 3

BUỔI 5: Áp dụng Bootstrap 3 vào xây dựng giao diện web

BUỔI 6: Xây dựng trang thương mại điện tử cơ bản [thực hành xây dựng trang chi tiết sản phẩm]

BUỔI 7: JavaScript cơ bản

BUỔI 8: Jquery cơ bản, Jquery selector, jQuery Effects và Jquery Ajax

BUỔI 9: Jquery cơ bản, Jquery selector, jQuery Effects và Jquery Ajax

BUỔI 10: Hoàn thiện trang chi tiết sản phẩm [áp dụng html5, css3, js]

BUỔI 11: Giới thiệu về Angular 5 và một số framework js

BUỔI 12: Hệ thống kiến thức và duyệt đề tài + support project Frontend.

BUỔI 13: Hệ thống kiến thức và duyệt đề tài + support project Frontend.

BUỔI 14: Hệ thống kiến thức và duyệt đề tài + support project Frontend

[ PHẦN 2: C# CƠ BẢN ]

Thời lượng:  09   buổi

BUỔI 1: Giới thiệu về C#, kiểu dữ liệu, biến, hằng, toán tử

BUỔI 2: Vòng lặp và câu lệnh điều kiện, các bài tập thực hành

BUỔI 3: String và String buider, mảng dữ liệu, các thao tác với mảng

BUỔI 4: Ép kiểu, xử lý ngoại lệ, tham chiếu, tham trị

BUỔI 5 : Giới thiệu về Collection, và genneric trong C#

BUỔI 6: Giới thiệu về lập trình Hướng đối tượng. Object, Class

BUỔI 7: Các tính chất của lập trình hướng đối tượng [Tính đóng gói và tính kế thừa]

BUỔI 8: Các tính chất của lập trình hướng đối tượng [Tính đa hình và trừu tượng]

BUỔI 9: Thực hành lập trình hướng đối tượng

[ PHẦN 3: Xây dựng ứng dụng web với Asp.net MVC+ Web API  ]

Thời lượng:  21   buổi

I - SQL server và Entity framework [5 buổi]

BUỔI 1: Tổng quan về SQL server

BUỔI 2: Cách phân tích thiết kế CSDL của 1 hệ thống

BUỔI 3: Giới thiệu về Entity framework

BUỔI 4: Hướng dẫn sử dụng code first trong việc tạo và kết nối CSDL

BUỔI 5: Sử dụng Linq để truy vấn dữ liệu

II - Xây dựng web thương mại với Asp.net [16 buổi]

BUỔI 1: Tổng quan về mô hình ASP.NET MVC; Asp.net Core, Application structure, life cycle

BUỔI 2: Asp.net Middleware, các cấu hình trong Asp.net core

BUỔI 3: Giới thiệu về nguyên lý Rest, Restfull API và web api, Sử dụng postman để test các Web api

BUỔI 4: Giới thiệu về mô hình MVC, controller, Action, model

BUỔI 5: View model, DTO, giới thiệu về thư viện automapper. Thực hành CRUD đơn giản

BUỔI 6: Xây dựng Framework sử dụng pattern repository và unit of work

BUỔI 7: Xây dựng Framework sử dụng pattern repository và unit of work [tiếp theo]

BUỔI 8: Asp.net Core Dependency Injection. Kết nối với DB và hoàn thiện form

BUỔI 9: Handle exception và response data

BUỔI 10: Làm việc với Asp.net Identity [Quản lý users và phân quyền]

BUỔI 11: Asp.net Identity phần 2. tạo hệ thống các api hoàn chỉnh

BUỔI 12: Bảo mật API [JWT, OAuth] và cách đón, truyền tham số từ giao diện

BUỔI 13: Giới thiệu qua về các framework JS [Reactjs, Angular, Vue], Axios

BUỔI 14-16: Triển khai và support Project [Thực hành tạo chi tiết sản phẩm và web thương mại điện tử; cấu hình và triển khai ứng dụng

asp.net mvc solution’s architecture

Previous post

Trước khi đi vào kiến trúc của project, mình sẽ nói thêm đôi chút về database.

DbContext

1 thủ thuật nhỏ giúp bạn tiết kiệm thời gian là sử dụng directive của .net để nhanh chóng “switch” connection string giữa môi trường dev và product.

Với connection string được config trong .config

Khi sử dụng build ở mode RELEASE, directive #elif !DEBUG sẽ được sử dụng, và connection string được chỉ định là ProductConnection

Mình cũng đã cập nhật entity để thể hiện mối quan hệ. Ở đây mình không sử dụng lazy loading mà dùng eager loading. Mình cũng đã có 1 bài viết để giải thích về 2 khái niệm này, bạn có thể xem tại đây.

Thể hiện mối quan hệ bằng navigation property:

Một số entity mình để trống, sẽ cập nhật sau này. Và mình sẽ nói tới cách giải quyết vấn đề khi có sự thay đổi entity.

Kiến trúc Project

Trước khi đi vào chi tiết, mình xin nói rõ những kiến thức trong bài viết hoàn toàn thuộc về kinh nghiệm bản thân, được đúc kết trong quá trình làm việc, tìm hiểu và cày cuốc. Do đó đây không phải là 1 tiêu chuẩn, và tất nhiên không tránh khỏi thiếu sót. Mình rất hoan nghênh nhận xét đánh giá của mọi người để cùng nhau hoàn thiện.

Mục tiêu của những bài viết của mình là dành cho những người ..chưa biết, đọc vào cũng hiểu. Để làm được điều đó, bạn đừng cố gắng hiểu những gì chưa cần hiểu :]. Cụ thể ở đây là về mặt kỹ thuật. Hãy nắm bắt “tư tưởng” trước, sau khi đả thông tư tưởng, bạn hoàn toàn có thể tự implement theo cách của bản thân, hoặc, follow theo hướng dẫn.

Ok, vậy mình sẽ nói về tư tưởng:

Mình đang có vốn và mình có nhu cầu bán điện thoại di động online, do đó mình cần 1 web app có thể show hàng, bán hàng và thanh toán cùng các chức năng lẻ tẻ khác:

Thằng bạn của mình là dev, nó biết được nhu cầu của mình nên mới nói: "ei mài, tao có thể cung cấp cho mày các API để show hàng và mua/bán hàng đó, team của tao luôn cập nhật công nghệ mới nhất nên mày an tâm về các khoản bla bla.. đi". Mình nghĩ: "Oh! ngon, quất thôi, ngại gì vết bẩn":

Vậy là team mình làm việc với team business [bus] của thằng bạn để tích hợp 2 hệ thống với nhau. Bên mình chỉ cần làm xong giao diện [UI], bên nó sẽ lo phần bus logic.

Lại nói về thằng bạn mình, nó có 1 team toàn super-dev nên cũng kiếm được kha khá khách hàng. Có lần nó kể khách hàng của nó người muốn dùng sql server, người muốn dùng mongodb, lại có khách sộp muốn dùng oracle...Mình mới thắc mắc là nếu có 1 chút business thay đổi chắc team nó phải làm việc cật lực lắm mới đảm bảo được sự nhất quán giữa các data source. Nó mới cười: "Đơn giản lắm mày à, tao dùng repository nên ~~adapt rất nhanh với các thay đổi”.~~

Á à, thì ra nó tổ chức mô hình theo kiểu này...[bế tắc để viết]

...todo

Từ mô hình trên có thể thấy..[bế tắc để viết luôn]

#### TL;DR

Ok, vậy là bỏ qua phần tư tưởng :v. Dev mà văn vẻ dài dòng quá cũng khó chịu :]]

Nói nhanh cho vuông thì đây được xem là kiến trúc 3 tiers [storage và repo được xem là 1 tier].

AutoMapper và Domain entities

Có thể thấy ngay, tầng app chỉ quan tâm tới business, không quan tâm tới việc data lưu trữ như thế nào. Vậy nên cái được luân chuyển qua lại giữa các tầng là 1 object dùng để transfer data, mà mình gọi là domain object [hoặc Data Transfer Object - DTO]. Như vậy ở application và business bạn không cần phải cài đặt các library như entity framework hoặc driver kết nối data nữa.

Xem bài viết của mình tại đây để biết về AutoMapper, hoặc xem full document tại đây.

Để sử dụng kỹ thuật Dependency Injection thì bạn có thể đọc bài viết này của mình, hoặc xem full document tại đây.

Mình sẽ nói kỹ hơn về automapper và autofac trong lúc sử dụng.

Ok, giờ mình nói chi tiết vào các phần của solution:

1st tier: didongexpress.repos

Project này implement repository pattern [repo] và unit of work pattern [uow]. repo cung cấp các phương thức CRUD cơ bản để làm việc với 1 data source, và uow đảm bảo các repo dùng chung 1 instance của db tại 1 thời điểm.

Bạn có thể đọc bài viết này của mình để nắm về repository pattern, hoặc đọc giải thích 1-cách-kỹ-thuật của microsoft tại đây.

Trong implementation của mình có 1 nhược điểm là đã gán trực tiếp DbContext cho repository, điều này không thể hiện đúng sức mạnh của repo. Mình sẽ “generic” nó trong 1 bài viết khác, và hy vọng bạn cũng chia sẻ cách làm của mình :]

Sau khi có generic repo, bạn chỉ cần kế thừa nó và sử dụng:

1 điều chú ý là việc mapping giữa entity object và domain object để truyền lên business tier. Tại sao cần phải map? Như đã nói ở trên, app và bus không cần quan tâm tới việc lưu trữ ở database, do đó, ít nhất ở đây là nó không cần phải add reference tới db dll. Hơn nữa, mỗi khi có sự thay đổi ở db [hoặc bus], mình chỉ cần đổi phương thức map là xong. [Xem code hoặc link trên để biết cách setup map].

Về UoW, chỉ gồm 2 phương thức, được implement như sau:

Đây là nơi mà instance của DbContext được sinh ra, và truyền vào constructor của các repositories => đảm bảo được tất cả các repo đều dùng chung 1 instance của db context. Ở đây mình sử dụng kiểu Lazy để tránh việc khởi tạo các repo khi chưa thực sự sử dụng.

Một lần nữa ở đây đã gán trực tiếp DbContext vào UoW, và nó không thể hiện được sức mạnh “switch” data source, tuy nhiên điều này không đáng nói ở series này.

Phương thức Get dùng để lấy 1 repo đã được “đăng ký”, điều này cũng có thể đạt được bằng cách khai báo các “read-only” properties trên interface UnitOfWork.

Toàn bộ project didongexpress.repo có thể tóm gọn trong class diagram sau:

2nd tier: didongexpress.bus

Tầng này vô cùng đơn giản, nó quy định các business [công việc, method, function - tùy cách gọi của bạn] cho ứng dụng, và gọi xuống repository để lấy data và trả data về cho app:

có 2 điều cần chú ý trong ProductBusiness:

  1. Kế thừa từ base Business: điều này là optional, nhưng nếu có thì nó sẽ giúp bạn dễ dàng thêm các “bước” cho 1 business process: Validate -> PreProcess -> Process -> PostProcess…

  2. Dependency Injection: IUnitOfWork được “inject” vào ProductBusiness, điều này dễ dàng đạt được bằng cách sử dụng autofac, và điều cần thiết là config cho nó [clone source về xem cho đã mắt, F12 các kiểu để thấy mối liên hệ]:

didongexpress.bus diagram:

3th tier: didongexpress

Đây là cái web app của bạn, công việc bây giờ đơn giản lắm, bạn chỉ cần gọi tới thằng business, thi thoảng validate input hoặc xử lý file…

Ở đây cũng inject business vào constructor của controller, rồi cứ thế mà gọi phương thức cần ra thôi.

Tất nhiên là bạn cũng phải setup mapper và ioc các kiểu, thằng mà để làm cái này chả còn ai khác ngoài Application_Start:

Ok, Recap

Có 1 câu nói rất hay, mà mình chả nhớ là của cha nào [mình đọc quote rất ít khi nhớ tên tác giả :v, còn nữa, đại ý là thế thôi, mình cũng chả nhớ nguyên văn đâu :]]]

Nếu bạn muốn làm 1 cái gì đó to, đừng làm cái to. Hãy làm những cái nhỏ và gộp nó lại.

Câu nói trên rất đúng khi bạn phát triển ứng dụng. 1 khi ứng dụng của bạn đạt độ lớn vừa đủ, việc làm theo 1 mô hình chia nhỏ giúp bạn tiết kiệm rất nhiều thời gian + công sức cho việc maintain, upgrade, fix bug, testing…vì bạn thấy đấy, việc gì ra việc đó rồi, làm gì cũng biết làm ở đâu rồi.

Bạn nghĩ, ôi! việc gì phải làm phức tạp vấn đề lên như vậy, cứ gom 1 cục vào 1 project mà chiến, project này nhỏ mà. :]] Thi thoảng mình làm biếng cũng chẳng chia chác làm gì đâu [nếu cái là nhỏ, “thực sự nhỏ”]. Việc làm theo mô hình giúp bạn giải quyết các vấn đề khi 1 project đạt độ lớn [độ lớn ở đây là độ phức tạp, nhiều file, nhiều dll, …] nhất định, cho nên không phải lúc nào áp dụng vào tất cả cũng tốt.

Và cuối cùng, đây là 1 bài viết trong asp.net mvc series của mình, series này mình hướng tới những ai chưa biết, hoặc chưa nắm rõ asp.net mvc. Và dễ hiểu nếu bạn thấy bài này khó hiểu. Khi đó bạn có 3 cách: hoặc là clone code về, F5, F10, F11, F12 để xem luồng đi của sự kiện; hoặc, bỏ qua bài này, vì nó chả liên quan gì tới mvc cả; hoặc, cách cuối cùng là bỏ luôn series này, thằng này viết như củ kẹc ấy :v, đã viết chậm lại viết khó hiểu :]]]

Luôn sẵn lòng đón nhận ý kiến đóng góp từ ae hoặc thắc mắc thầm kín của ae :]

Code luôn được up-to-date tại repo didongexpress, video fullhd không che cũng up-to-date tại playlist.

Chủ Đề