Northwind Database ဆိုတာ Microsoft က ဖန်တီးခဲ့တဲ့ classic sample Database တစ်ခုဖြစ်ပါတယ်။ သူက "Northwind Traders" လို့ခေါ်တဲ့ company တစ်ခုရဲ့ အရောင်းအဝယ် Data တွေကို ကိုယ်စားပြုပါတယ်။ Customer၊ Order နဲ့ Product table တွေပါဝင်တဲ့အတွက် အရောင်းရဆုံး product တွေကို ရှာဖွေခြင်းလိုမျိုး လက်တွေ့ကျတဲ့ query တွေရေးဖို့ လေ့ကျင့်နိုင်တာကြောင့် Tutorial တွေအတွက် အလွန်အသုံးဝင်ပါတယ်။
ပထမဆုံးအနေနဲ့ ကျွန်တော်တို့ရဲ့ SQL Server မှာ Northwind Database ရှိဖို့ လိုအပ်ပါတယ်။
- Download the
instnwnd.sqlscript from Microsoft's GitHub repository. - SQL Server Management Studio (SSMS) မှာ အဲ့ဒီ script ကို Execute လုပ်ပြီး
NorthwindDatabase ကို ဆောက်ပါမယ်။
အခု Visual Studio မှာ Solution နဲ့ Project တွေကို ဆောက်ပါမယ်။
- Create a Blank Solution:
NorthwindChartsဆိုတဲ့နာမည်နဲ့Blank Solutionတစ်ခု ဆောက်ပါမယ်။ - Create the Database Project:
NorthwindCharts.Databaseဆိုတဲ့ နာမည်နဲ့Class Libraryproject တစ်ခု ဆောက်ပါမယ်။ - Create the MVC Project:
NorthwindCharts.Mvcဆိုတဲ့ နာမည်နဲ့ASP.NET Core Web App (Model-View-Controller)project တစ်ခု ဆောက်ပါမယ်။
ကျွန်တော်တို့ dotnet ef CLI command ကိုသုံးပြီး Database ကနေ C# class တွေကို generate လုပ်ပါမယ်။
-
Install NuGet Packages:
NorthwindCharts.Databaseproject မှာ အောက်က package တွေကို Install လုပ်ပါ။Microsoft.EntityFrameworkCore.SqlServerMicrosoft.EntityFrameworkCore.ToolsMicrosoft.EntityFrameworkCore.Design
-
Run
dotnet efCLI Command:dotnet-eftool ကို install လုပ်ပြီးသားဖြစ်ဖို့ လိုအပ်ပါတယ်။ ကျွန်တော်တို့ရဲ့ Solution Folder ထဲကို terminal ကနေ သွားပြီး အောက်က command ကို run ပါမယ်။dotnet ef dbcontext scaffold "Server=.;Database=Northwind;User ID=sa;Password=sasa@123;TrustServerCertificate=True;" Microsoft.EntityFrameworkCore.SqlServer -o AppDbContextModels -c AppDbContext -f
ကျွန်တော်တို့ရဲ့ DbContext ကို MVC project ကနေ အလွယ်တကူ ခေါ်သုံးလို့ရအောင် Program.cs မှာ service တစ်ခုအနေနဲ့ မှတ်ပုံတင် (Register) လုပ်ပါမယ်။
- Add Project Reference:
NorthwindCharts.Mvcproject ကနေNorthwindCharts.Databaseproject ကို reference လုပ်ပါ။ - Register DbContext & Add Connection String:
NorthwindCharts.Mvcproject ရဲ့Program.csfile မှာDbContextကို register လုပ်ပြီးappsettings.jsonမှာ Connection String ကို ထည့်ပေးပါ။-
In
Program.cs:using Microsoft.EntityFrameworkCore; using NorthwindCharts.Database.Models; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); builder.Services.AddDbContext<AppDbContext>(options => { string connectionString = builder.Configuration.GetConnectionString("DbConnection"); options.UseSqlServer(connectionString); }); var app = builder.Build(); // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
-
In
appsettings.json:{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "DbConnection": "Server=.;Database=Northwind;User ID=sa;Password=sasa@123;TrustServerCertificate=True;" } }
-
Code မရေးခင်မှာ chart တွေ ဘယ်လိုအလုပ်လုပ်လဲဆိုတာကို ရိုးရှင်းတဲ့ ဥပမာလေးနဲ့ လေ့လာပြီး၊ ကျွန်တော်တို့ရဲ့ Data ကိုင်တွယ်ပုံကို ပိုကောင်းအောင်လုပ်ဖို့ DTO ကို အသုံးပြုပါမယ်။
ApexCharts လို charting library တွေက ရှုပ်ထွေးတဲ့ Data တွေကို နားမလည်ပါဘူး။ သူတို့က သတ်မှတ်ထားတဲ့ ရိုးရှင်းတဲ့ format နဲ့ပဲ Data ကို လက်ခံပါတယ်။ Pie chart တစ်ခုအတွက် အဓိကအားဖြင့် အရာနှစ်ခု လိုအပ်ပါတယ်-
- Labels Array: Chart အစိတ်ပိုင်းလေးတွေရဲ့ နာမည်တွေ (ဥပမာ- product အမည်များ)။
- Series Array: အစိတ်ပိုင်းတစ်ခုချင်းစီရဲ့ တန်ဖိုးကိန်းဂဏန်းများ (ဥပမာ- ရောင်းရအရေအတွက်)။
အောက်မှာ static "dummy" data ကိုသုံးထားတဲ့ ဥပမာကို ရေးပြပါမယ်။
// Dummy data
var labels = ['Product A', 'Product B', 'Product C'];
var series = [150, 200, 120];
var options = {
chart: { type: 'pie' },
labels: labels, // ဒီနေရာမှာ ကျွန်တော်တို့ရဲ့ product နာမည်တွေ လာပါမယ်။
series: series // ဒီနေရာမှာ ကျွန်တော်တို့ရဲ့ အရောင်းအရေအတွက်တွေ လာပါမယ်။
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();ကျွန်တော်တို့ရဲ့ ရည်ရွယ်ချက်ကတော့ ဒီ static labels နဲ့ series array တွေကို ကျွန်တော်တို့ရဲ့ Database ကနေရလာတဲ့ dynamic Data နဲ့ အစားထိုးဖို့ပါပဲ။
ကျွန်တော်တို့ရဲ့ database query ကနေ ရှုပ်ထွေးတဲ့ object တွေပြန်မလာစေဘဲ၊ chart အတွက်လိုအပ်တဲ့ Data တွေကိုပဲ သီးသန့်သယ်ဆောင်ပေးမယ့် class လေးတစ်ခုကို ဆောက်ပါမယ်။ ဒါကို Data Transfer Object (DTO) လို့ခေါ်ပါတယ်။ ဒါက ကျွန်တော်တို့ရဲ့ code ကို ပိုပြီးရှင်းလင်းစေပြီး နားလည်ရလွယ်ကူစေပါတယ်။
-
NorthwindCharts.Mvcproject မှာDtosဆိုတဲ့ Folder အသစ်တစ်ခု ဆောက်ပါ။ -
အဲ့ဒီ Folder ထဲမှာ
BestSellingProductDto.csဆိုတဲ့ class file အသစ်ဆောက်ပြီး အောက်က code ကို ရေးပြပါမယ်။namespace NorthwindCharts.Dtos { public class BestSellingProductDto { public string ProductName { get; set; } public int TotalQuantity { get; set; } } }
အခု ကျွန်တော်တို့ Controller ကို ဆောက်ပါမယ်။ LINQ အစား ပိုရှင်းလင်းပြီး performance ပိုကောင်းနိုင်တဲ့ raw SQL query ကို FromSqlRaw နဲ့ အသုံးပြုသွားပါမယ်။
ကျွန်တော်တို့ရဲ့ Data ကိုရဖို့အတွက် table နှစ်ခုကို အသုံးပြုဖို့ လိုအပ်ပါတယ်-
[Order Details]: ဒီ table က order တစ်ခုချင်းစီမှာ ရောင်းချခဲ့တဲ့ product တွေရဲ့Quantity(အရေအတွက်) ပါဝင်တဲ့အတွက် အလွန်အရေးကြီးပါတယ်။Products: ဒီ table မှာတော့[Order Details]table ထဲကProductIDနဲ့ ချိတ်ဆက်ပြီး Product ရဲ့ နာမည်ProductNameကို ရယူဖို့ သုံးပါမယ်။
ကျွန်တော်တို့က ဒီ table နှစ်ခုကို JOIN လုပ်ပြီး product နာမည်နဲ့ ရောင်းရအရေအတွက်ကို ချိတ်ဆက်ပေးမှာ ဖြစ်ပါတယ်။
Controllers Folder ထဲမှာ DashboardController.cs ကို ဆောက်ပြီး အောက်က code ကို ရေးပြပါမယ်။
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NorthwindCharts.Mvc.Dtos; // ကျွန်တော်တို့ရဲ့ DTO ကို import လုပ်ပါမယ်။
using NorthwindCharts.Database.Models;
namespace NorthwindCharts.Mvc.Controllers
{
public class DashboardController : Controller
{
private readonly AppDbContext _db;
public DashboardController(AppDbContext db)
{
_db = db;
}
public IActionResult Index()
{
return View();
}
[HttpGet]
public async Task<IActionResult> GetBestSellingProducts()
{
// ရောင်းရအရေအတွက်အလိုက် အရောင်းရဆုံး product ၅ ခုကို ဆွဲထုတ်မယ့် Raw SQL Query ပါ။
var sqlQuery = @"
SELECT TOP 5
P.ProductName,
SUM(OD.Quantity) AS TotalQuantity
FROM
[Order Details] OD
JOIN
Products P ON OD.ProductID = P.ProductID
GROUP BY
P.ProductName
ORDER BY
TotalQuantity DESC";
// FromSqlRaw ကိုသုံးပြီး Query ကရလာတဲ့ Data တွေကို ကျွန်တော်တို့ရဲ့ DTO ထဲကို ထည့်ပါမယ်။
var topProducts = await _db.Database
.SqlQueryRaw<BestSellingProductDto>(sqlQuery)
.ToListAsync();
return Json(topProducts);
}
}
}ပိုပြီး စနစ်တကျရှိစေဖို့ chart library JavaScript file တွေကို main layout file မှာ ထည့်သွင်းပါမယ်။ ဒါမှ ဒီ library တွေကို လိုအပ်တဲ့ page တိုင်းက အလွယ်တကူ သုံးနိုင်မှာ ဖြစ်ပါတယ်။
Views/Shared/_Layout.cshtml ကိုဖွင့်ပြီး @await RenderSectionAsync("scripts", required: false) ဆိုတဲ့ line ရဲ့ အပေါ်မှာ <script> tag နှစ်ခုကို ထပ်ထည့်ပေးပါ။
<!DOCTYPE **html**>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - NorthwindCharts.Mvc</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/NorthwindCharts.Mvc.styles.css" asp-append-version="true" />
</head>
<body>
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
<div class="container-fluid">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">NorthwindCharts.Mvc</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<main role="main" class="pb-3">
@RenderBody()
</main>
</div>
<footer class="border-top footer text-muted">
<div class="container">
© 2025 - NorthwindCharts.Mvc - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("scripts", required: false)
</body>
</html>နောက်ဆုံးအနေနဲ့ chart တွေကိုပြမယ့် view ကို ဆောက်ပါမယ်။ ဒီနေရာမှာ @section scripts block အကြောင်းကိုလည်း ရှင်းပြသွားပါမယ်။
@section scripts ဆိုတာ Razor view (ဥပမာ Index.cshtml) မှာသုံးတဲ့ အထူး block တစ်ခုဖြစ်ပါတယ်။ ဒီ block ထဲမှာ ထည့်သွင်းလိုက်တဲ့ HTML ဒါမှမဟုတ် JavaScript code တွေက _Layout.cshtml file ထဲက @RenderSection("scripts") လို့ခေါ်ထားတဲ့ နေရာမှာ အလိုအလျောက် သွားရောက်ပေါ်နေမှာ ဖြစ်ပါတယ်။ ဒါက page တစ်ခုချင်းစီအတွက် သီးသန့် script တွေထည့်သွင်းတဲ့ standard နည်းလမ်းဖြစ်ပြီး၊ jQuery လို main library တွေ load ဖြစ်ပြီးမှသာ page-specific script တွေ load ဖြစ်တာကို သေချာစေပါတယ်။
ပြီးရင် Views/Dashboard/Index.cshtml ကို အောက်က code နဲ့ ဆောက်ပါမယ်။
@{
ViewData["Title"] = "Sales Dashboard";
}
<h1 class="mb-4">Sales Dashboard</h1>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-header">
Top 5 Best-Selling Products (ApexCharts)
</div>
<div class="card-body">
<div id="apexPieChart"></div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-header">
Top 5 Best-Selling Products (HighCharts)
</div>
<div class="card-body">
<figure class="highcharts-figure">
<div id="highchartsPieChart"></div>
<p class="highcharts-description" style="text-align: center; font-size: 0.8em; margin-top: 1em;">
This chart shows a comparison of the top 5 products based on quantity sold.
</p>
</figure>
</div>
</div>
</div>
</div>
@section scripts {
<script>
$(document).ready(function () {
// ကျွန်တော်တို့ရဲ့ controller endpoint ကနေ Data ကို သွားယူပါမယ်။
$.ajax({
url: "/dashboard/getbestsellingproducts",
type: "get",
success: function (data) {
renderApexChart(data);
renderHighCharts(data);
},
error: function (xhr) {
console.error("failed to load chart data:", xhr.responseText);
}
});
});
function renderApexChart(data) {
// Data ကို ApexCharts format ဖြစ်အောင် ပြောင်းပါမယ်။
const chartLabels = data.map(item => item.productName);
const chartSeries = data.map(item => item.totalQuantity);
const options = {
series: chartSeries,
chart: {
width: 380,
type: 'pie',
},
labels: chartLabels,
responsive: [{
breakpoint: 480,
options: {
chart: {
width: 200
},
legend: {
position: 'bottom'
}
}
}]
};
const chart = new ApexCharts(document.querySelector("#apexPieChart"), options);
chart.render();
}
function renderHighCharts(data) {
// Data ကို HighCharts format ဖြစ်အောင် ပြောင်းပါမယ်။
const chartSeries = data.map((item, index) => ({
name: item.productName,
y: item.totalQuantity,
// Make the first slice selected and popped out
sliced: index === 0,
selected: index === 0
}));
Highcharts.chart('highchartsPieChart', {
chart: {
type: 'pie'
},
title: {
text: 'Top 5 Best Sellers'
},
tooltip: {
pointFormat: '<b>{point.y}</b> units sold'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %'
}
}
},
series: [
{
name: 'Quantity',
colorByPoint: true,
data: chartSeries
}
]
});
}
</script>
}Views/Shared/_Layout.cshtml ကိုဖွင့်ပြီး navigation bar မှာ အောက်က link ကို ထည့်ပေးပါ။
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="Dashboard" asp-action="Index">Dashboard</a>
</li>ပြီးရင်တော့ ကျွန်တော်တို့ရဲ့ project ကို Run ပြီး စမ်းသပ်ကြည့်နိုင်ပါပြီ။ Dashboard page မှာ Raw SQL query နဲ့ Database ကနေ dynamic ဆွဲထုတ်ထားတဲ့ Data တွေနဲ့ ပြသထားတဲ့ pie chart နှစ်ခုကို တွေ့မြင်ရမှာဖြစ်ပါတယ်ခင်ဗျာ။