Xây dựng bộ đếm số người truy cập website với asp.net - Csharp

Trong bài viết "Thống kê truy cập website" tôi đã hướng dẫn bạn thống kê truy cập website qua text. Có bạn gửi yêu cầu viết bài thống kế với SQL server. Đáp ứng yêu cầu trong bài này tôi sẽ hướng dẫn các bạn xây dựng một bộ đếm thống kê truy cập website đầy đủ bằng asp.net - C# sử dụng SQL server.

Trong bài viết này tôi hướng dẫn bạn thống kê số truy cập Hôm nay, Hôm qua, Tuần này, ... Đây là hình ảnh minh họa kết quả khi bạn thực hiện theo bài viết này:
Để làm được bạn cần tạo một bảng TB_ThongKe như sau:
CREATE TABLE [dbo].[TB_ThongKe](
 [MaTB] [int] IDENTITY(1,1) PRIMARY KEY  NOT NULL,
 [ThoiGian] [datetime] NOT NULL,
 [SoTruyCap] [bigint] NOT NULL,
)
Tiếp theo bạn cần viết một Store Procedure để thực hiện việc thông kê như sau:
/*
 Create by : HMCLIP ADMIN
 Des  : Thống kê truy cập website
 */
CREATE PROCEDURE [dbo].[spThongKe_Edit]
AS
BEGIN
 DECLARE @SoTruyCapGanNhat bigint
 DECLARE @Count int
 SELECT @Count=Count(*) FROM TB_ThongKe ttk
 IF @Count IS NULL SET @Count=0
 IF @Count=0
  INSERT INTO TB_ThongKe(ThoiGian, SoTruyCap)
  VALUES (GetDate(),1)
 ELSE
  BEGIN
   
   DECLARE @ThoiGianGanNhat datetime
   SELECT @SoTruyCapGanNhat=ttk.SoTruyCap, @ThoiGianGanNhat=ttk.ThoiGian
     FROM TB_ThongKe ttk WHERE ttk.MaTB=(SELECT Max(ttk2.MaTB) FROM TB_ThongKe ttk2)
   IF @SoTruyCapGanNhat IS NULL SET @SoTruyCapGanNhat=0
   IF @ThoiGianGanNhat IS NULL SET @ThoiGianGanNhat=getdate()
   -- Kiểm tra xem lần truy cập này có phải đã sang ngày mới không (Qua thời điểm 12h00)
   -- Nếu chưa sang ngày mới thì cập nhật lại SoTruyCap
   IF Day(@ThoiGianGanNhat)=Day(GETDATE())
    BEGIN
     UPDATE TB_ThongKe
     SET
      SoTruyCap = @SoTruyCapGanNhat+1,
      ThoiGian = GetDate()
      
     WHERE MaTB=(SELECT Max(ttk2.MaTB) FROM TB_ThongKe ttk2)
    END
    -- Nếu đã sang ngày mới thì thêm mới bản ghi, SoTruyCap bắt đầu lại là 1
   ELSE
    BEGIN
     INSERT INTO TB_ThongKe(ThoiGian, SoTruyCap)
     VALUES (GetDate(),1)
    END
  END
 
  -- Thống kê Hom nay, Hom qua, Tuan nay, Tuan Truoc, Thang nay, Thang Truoc
  DECLARE @HomNay INT
  SET @HomNay = datepart(dw, GetDate())
  SELECT @SoTruyCapGanNhat=ttk.SoTruyCap, @ThoiGianGanNhat=ttk.ThoiGian
     FROM TB_ThongKe ttk WHERE ttk.MaTB=(SELECT Max(ttk2.MaTB) FROM TB_ThongKe ttk2)
  --Tính SoTruyCapHomQua
  DECLARE @SoTruyCapHomQua bigint
  SELECT @SoTruyCapHomQua=isnull(SoTruyCap,0) FROM TB_ThongKe  
   WHERE CONVERT(nvarchar(20),ThoiGian,103)=CONVERT(nvarchar(20),GETDATE()-1,103)
  IF @SoTruyCapHomQua IS null SET @SoTruyCapHomQua=0
  -- Tính Ngày đầu tuần này
  DECLARE @DauTuanNay datetime
  SET @DauTuanNay= DATEADD(wk, DATEDIFF(wk, 6, GetDate()), 6)
  -- Tính Ngày đầu của tuần trước Tính từ thời điểm 00:00:))
  DECLARE @NgayDauTuanTruoc datetime
  SET @NgayDauTuanTruoc = Cast(CONVERT(nvarchar(30),DATEADD(dd, -(@HomNay+6), GetDate()),101) AS datetime)
  -- Tính ngày cuối tuần trước tính đến 24h ngày cuối tuần 
  DECLARE @NgayCuoiTuanTruoc datetime
  SET @NgayCuoiTuanTruoc = Cast(CONVERT(nvarchar(30),DATEADD(dd, -@HomNay, GetDate()),101) +' 23:59:59' AS datetime)
  
  -- Tính số truy cập tuần này
  DECLARE @SoTruyCapTuanNay bigint
  SELECT @SoTruyCapTuanNay=isnull(Sum(SoTruyCap),0) FROM TB_ThongKe ttk 
   WHERE ttk.ThoiGian BETWEEN @DauTuanNay AND getdate()
   
  -- Tính số truy cập tuần trước
  DECLARE @SoLanTruyCapTuanTruoc bigint
  SELECT @SoLanTruyCapTuanTruoc=isnull(sum(SoTruyCap),0)  FROM TB_ThongKe ttk 
   WHERE ttk.ThoiGian BETWEEN @NgayDauTuanTruoc AND @NgayCuoiTuanTruoc
  
  -- Tính số truy cập tháng này
  DECLARE @SoTruyCapThangNay bigint 
  SELECT @SoTruyCapThangNay=isnull(Sum(SoTruyCap),0)
   FROM TB_ThongKe ttk WHERE MONTH(ttk.ThoiGian)=MONTH(GETDATE())
  
  -- Tính số truy cập tháng trước
  DECLARE @SoTruyCapThangTruoc bigint 
  SELECT @SoTruyCapThangTruoc=isnull(Sum(SoTruyCap),0)
   FROM TB_ThongKe ttk WHERE MONTH(ttk.ThoiGian)=MONTH(GETDATE())-1
  
  -- Tính tổng số
  DECLARE @TongSo bigint
  SELECT  @TongSo=isnull(Sum(SoTruyCap),0) FROM TB_ThongKe ttk
  
  SELECT @SoTruyCapGanNhat AS HomNay, 
  @SoTruyCapHomQua AS HomQua,
  @SoTruyCapTuanNay AS TuanNay, 
  @SoLanTruyCapTuanTruoc AS TuanTruoc, 
  @SoTruyCapThangNay AS ThangNay, 
  @SoTruyCapThangTruoc AS ThangTruoc,
  @TongSo AS TatCa
END
Đọc Store trên có thể bạn sẽ hơi khó hiểu nếu bạn không thành thạo lập trình với SQL. Trước tiên bạn cần kiểm tra xem nếu chưa có dữ liệu thì thêm mới. Và nếu lượt truy cập tiếp theo là thời gian bắt đầu sang ngày tiếp theo bạn lại thực hiện thêm bản ghi vào bảng TB_ThongKe. các trường hợp khác đều cập nhật dữ liệu với bản ghi cuối của TB_ThongKe
Để thực hiện thống kê bạn cần viết công thức tính các số liệu của
- Hôm nay=Tổng số truy cập của ngày hiện tại (Lấy giờ hệ thống của Database Server)
- Hôm qua=Tổng số truy cập của ngày gần nhất khác hôm qua
- Tuần này: Tổng số truy cập của các ngày trong tuần hiện tại => bạn cần tính đầu tuần và cuối tuần này là ngày nào và tình tổng theo đều kiện BETWEEN (Bạn chú ý là cần lấy dữ liệu ngày đầu tuần bắt đầu từ 00:00:00 và đến 23:59:59 của ngày cuối tuần).
- Tuần trước: Tổng số truy cập của các ngày của tuần trước => bạn cần tính đầu tuần và cuối tuần trước là ngày nào và tình tổng theo đều kiện BETWEEN (Bạn chú ý là cần lấy dữ liệu ngày đầu tuần bắt đầu từ 00:00:00 và đến 23:59:59 của ngày cuối tuần).
- Các điều kiện tháng này, tháng trước, tổng số cũng tương tự
*** Qua đây bạn cũng biết cách xác định được ngày đầu và ngày cuỗi của Tuần này, tuần trước, ... Tôi nghĩ là nó khá hay với ai thường lập trình trên SQL để tính toán dữ liệu liên quan đến ngày tháng

Bạn tạo trong App_Code class DataBindSQL.cs để thực hiện kết nối và trả về dữ liệu DataTable như sau:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
public class DataBindSQL
{
    public DataBindSQL()
    {
    }
    //Hàm thực thi và trả về DataTable
    public DataTable TableThongKe()
    {
        DataTable dtb = new DataTable();
        // Khai báo chuỗi kết nối
        string ConnectionString =
        @"Server =.\SQL2005;Initial Catalog=QuanLyThuVien;User ID=sa;Password=sa";
        SqlConnection Conn = new SqlConnection(ConnectionString);
        try
        {
             // Mở kết nối
            Conn.Open();
            DataSet ds = new DataSet();
            SqlCommand cmdUpd = new SqlCommand("spThongKe_Edit", Conn);
            cmdUpd.CommandType = CommandType.StoredProcedure;
            SqlDataAdapter da = new SqlDataAdapter(cmdUpd);
            // Đổ dữ liệu vào DataSet
            da.Fill(ds);
            dtb = ds.Tables[0];
        }
        catch { }
        finally
        {
            if (Conn.State == ConnectionState.Open)
                Conn.Close();
            Conn.Dispose();
        }
        return dtb;
    }
}

Tiếp theo bạn viết trong Global.asax nội dung như sau:
<%@ Application Language="C#" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data" %>
<script runat="server">
    void Application_Start(object sender, EventArgs e) 
    {
        // Code that runs on application startup
        Application["HomNay"] = 0;
        Application["HomQua"] = 0;
        Application["TuanNay"] = 0;
        Application["TuanTruoc"] = 0;
        Application["ThangNay"] = 0;
        Application["ThangTruoc"] =0;
        Application["TatCa"] = 0;
        Application["visitors_online"] = 0;
    }
    
    void Application_End(object sender, EventArgs e) 
    {
        //  Code that runs on application shutdown
    }
    void Application_Error(object sender, EventArgs e) 
    { 
        // Code that runs when an unhandled error occurs
    }
    void Session_Start(object sender, EventArgs e)
    {
        Session.Timeout = 150;
        Application.Lock();
        Application["visitors_online"] = Convert.ToInt32(Application["visitors_online"]) + 1;
        Application.UnLock();
        try
        {
            DataBindSQL mThongKe = new DataBindSQL();
            DataTable dtb = mThongKe.TableThongKe();
            if (dtb.Rows.Count > 0)
            {
                Application["HomNay"] = long.Parse("0" + dtb.Rows[0]["HomNay"]).ToString("#,###");
                Application["HomQua"] = long.Parse("0" + dtb.Rows[0]["HomQua"]).ToString("#,###");
                Application["TuanNay"] = long.Parse("0" + dtb.Rows[0]["TuanNay"]).ToString("#,###");
                Application["TuanTruoc"] = long.Parse("0" + dtb.Rows[0]["TuanTruoc"]).ToString("#,###");
                Application["ThangNay"] = long.Parse("0" + dtb.Rows[0]["ThangNay"]).ToString("#,###");
                Application["ThangTruoc"] = long.Parse("0" + dtb.Rows[0]["ThangTruoc"]).ToString("#,###");
                Application["TatCa"] = long.Parse("0" + dtb.Rows[0]["TatCa"]).ToString("#,###");
            }
            dtb.Dispose();
            mThongKe = null;
        }
        catch { }

    }
    void Session_End(object sender, EventArgs e) 
    {
        Application.Lock();
        Application["visitors_online"] = Convert.ToUInt32(Application["visitors_online"]) - 1;
        Application.UnLock();
    }
</script>
Vậy ở nơi bạn cần hiển thị thống kế bạn chỉ cần đưa các giá trị Application["HomNay"], Application["HomQua"] ,... Tương ứng. Bạn nên xây dựng một UserControl (ucThongKe.ascx) nội dung như sau
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ucThongKe.ascx.cs" Inherits="ucThongKe" %>
<asp:Panel ID="Panel1" runat="server" Width="250px" GroupingText="Thống kê truy cập">
    <table cellpadding="0" cellspacing="0" Width="250px" >
        
        <tr>
            <td style="width:50%; padding-left:10px">
               <img src="Common/Images/Import.png" /> Đang onlien:</td>
            <td style="width:50%">
                <% =Application["visitors_online"].ToString()%></td>
        </tr>
        <tr>
            <td style="width:50%; padding-left:10px">
                <img src="Common/Images/25.png" />Hôm nay:</td>
            <td style="width:50%">
                 <% =Application["HomNay"].ToString()  %></td>
        </tr>
        <tr>
            <td style="width:50%; padding-left:10px">
                <img src="Common/Images/25.png" /> Hôm qua:</td>
            <td style="width:50%">
                 <% =Application["HomQua"].ToString()  %></td>
        </tr>
        
         
        <tr>
            <td style="width:50%; padding-left:10px">
                <img src="Common/Images/AddUser.jpg" /> Tuần này:</td>
            <td style="width:50%">
                 <% =Application["TuanNay"].ToString()  %></td>
        </tr>
        <tr>
            <td style="width:50%; padding-left:10px">
                <img src="Common/Images/AddUser.jpg" /> Tuần trước:</td>
            <td style="width:50%">
                 <% =Application["TuanTruoc"].ToString()  %></td>
        </tr>
        <tr>
            <td style="width:50%; padding-left:10px">
                <img src="Common/Images/User.png" /> Tháng này:</td>
            <td style="width:50%">
                 <% =Application["ThangNay"].ToString()  %></td>
        </tr>
        <tr>
            <td style="width:50%; padding-left:10px">
                <img src="Common/Images/User.png" /> Tháng trước:</td>
            <td style="width:50%">
                 <% =Application["ThangTruoc"].ToString()  %></td>
        </tr>
        <tr>
            <td style="width:50%; padding-left:10px">
                <img src="Common/Images/02.jpg" />Tất cả:</td>
            <td style="width:50%">
                 <% =Application["TatCa"].ToString()%></td>
        </tr>
    </table>
 </asp:Panel>
 Khi đã viết xong UserControl trong trang asp.net bạn chỉ cần kéo thả control này vào và chạy.