css&javascript jquery使用ajax驗證帳號(運用介面、多型)

這篇比上篇還更難寫
這篇要求的功能其實不難:

當使用者輸入帳號後
帳號的框框一但失去焦點
馬上檢測是否有同帳號

聽起來很簡單吧!
不過後面連結資料的部份
才是觀念需要釐清的地方…


網頁註冊時滿常見的驗證功能,也很簡單
不過,這並不是這章的重點
這章其實主要在繼承及多型

為什麼會講到這個呢
上一篇文章第一步資料庫連結端
就是這次的重點啦!!

上篇的NWDB類別庫裡,最重要的就是SearchCustomer()這個方法
這樣寫沒有問題喔!不過在實務管理上會有點混亂,怎麼說呢?

今天是搜尋客戶,如果說,我想要搜尋產品,或搜尋價格
難道說就一直在NWDB.cs檔裡面不斷加新的方法嗎?
如果今天有2、3百個搜尋、更新要做,那管理上不就很困擾?
可能寫個「搜尋」的介面,再由需要做搜尋的方法去
實作可能會是比較妥當的管理方法。

簡單來說,我們現在要做的是資料庫連結端的再切割
並且在NWDB檔裡引入實作方法的行為
如此在使用上只要引用NWDB檔就即可

觀念如果搞懂,程式碼會做上一篇NWDB的修改
及加入驗證帳戶的功能


其中「介面」的cs有3個:
ICustomer.cs
Imember.cs
IProduct.cs   //這可以不要做,實際程式上也不會用到

真正在「實作」的cs有2個:
ImplCustomer.cs
ImplImember.cs

而NWDB呢,只是個空殼,會引入實作的方法
這部份真的有點抽像,我也不知道該怎麼用文字正確的敘述
打個比方可能比較容易懂:

NWDB是總承包商,自已不會做事
只是連接資料庫與中間商的橋梁
會分別放包給小的中間商,也就是介面

而中間商呢,也不會做事,就是畫好架構後
由最底層的工人來實作

如此層層分工,維護上會方便許多
在出問題時也比較容易找出徵結點

程式碼分別如下:

NWDB.cs:
//需實作3個介面的方法,IProduct可以不用
    public class NWDB : ICustomer, IProduct,IMember
{
    private SqlConnection cnn;
    public SqlConnection Connection
    {
        get { return this.cnn; }
    }        

    //建構子(建立資料庫連線)
    public NWDB()
    {
        cnn = new SqlConnection("server=localhost;database=中文北風;UID=SQLUser;PWD=1234");
    }

    //帶參數的建構子,引用時要加帳密
    public NWDB(string Account, string Password)
    {
        SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder();
        scsb.DataSource = "localhost";
        scsb.InitialCatalog = "中文北風";
        scsb.UserID = Account;
        scsb.Password = Password;
        scsb.IntegratedSecurity = false;

        cnn = new SqlConnection(scsb.ConnectionString);
    }

    //分別引入各介面
    private ICustomer ic;
    private IProduct ip;
    private IMember im;     
    public void SetCustomer(ICustomer ic)
    {
        this.ic=ic;
    }
    public void SetProduct(IProduct ip)
    {
        this.ip=ip;
    }
    public void SetMember(IMember im)
    {
        this.im = im;
    }

    //引入實作的方法
    #region 客戶
    public DataTable SearchCustomer(string CustomerName)
    {
        return ic.SearchCustomer(CustomerName);
    }
    #endregion
    #region 產品
    public DataTable SearchProduct()
    {
        return ip.SearchProduct();
    }
    #endregion
    #region 帳戶驗證
    public bool CheckMemberDuplicate(string Account)
    {
        return im.CheckMemberDuplicate(Account);
    }
    #endregion 帳戶驗證

    //解構子,確保有關閉資料庫連線
    ~NWDB()
    {
        cnn.Close();
        cnn.Dispose();
    }

}

ICustomer.cs:
//介面,由ImplCustomer來實作
public interface ICustomer
{        
    DataTable SearchCustomer(string CustomerName);
        
}

ImplCustomer.cs:
//實作ICustomer
public class ImplCustomer : ICustomer
{   
    private SqlConnection cnn;

    public ImplCustomer(SqlConnection cnn)
    {
        this.cnn = cnn;
    }
    //查詢客戶的程式碼
    public DataTable SearchCustomer(string CustomerName)
    {
        SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:00:01' SELECT 客戶編號,公司名稱,連絡人,連絡人職稱,地址 FROM 客戶 WHERE 公司名稱 LIKE ('%'+@cname+'%')", cnn);
        cmd.Parameters.Add("@cname", SqlDbType.VarChar).Value = CustomerName;

        cnn.Open();
        SqlDataReader mydr = cmd.ExecuteReader();
        DataTable tt = new DataTable();
        tt.Load(mydr);
        mydr.Close();
        cmd.Dispose();
        cnn.Close();

        return tt;
    }
}

IMember.cs:
public interface IMember
{
        bool CheckMemberDuplicate(string Account);
}

ImplImember.cs:
//實作IMember
public class ImplImember:IMember
{
    SqlConnection cnn;

    public ImplImember(SqlConnection cnn)
    {
        this.cnn = cnn;
    }
    //查詢帳戶有無重複的程式碼
    public bool CheckMemberDuplicate(string Account)
    {
        SqlCommand cmd = new SqlCommand("SELECT COUNT(*) FROM 會員表 WHERE 帳號 =@member", cnn);
        cmd.Parameters.Add("@member", SqlDbType.VarChar).Value = Account;
        cnn.Open();
        int nn = (int)cmd.ExecuteScalar();
        cmd.Dispose();
        cnn.Close();

        if (nn > 0)
            return true;
        else
            return false; 
    }
}

==========================================================================
以上就完成了NWDB類別庫的作法
後面就簡單了,跟上一篇的作法差不多:
一、用ashx撰寫泛式
二、選寫網頁端

由於本篇會改變上篇的引入方法,所以上篇的引入方法需更改:
//引入網頁傳來的值
string cname = context.Request.QueryString["cname"];
//new 出nwdb
NWDB.NWDB nwdb = new NWDB.NWDB();
//將nwdb中的連接方法傳給NWDB中ImplCustomer
NWDB.ImplCustomer im = new NWDB.ImplCustomer(nwdb.Connection);
//傳好後,將nwdb中設為im,如此nwdb.SearchCustome才會有值
nwdb.SetCustomer(im);
DataTable tt =nwdb.SearchCustomer(cname);
其他地方就不用更動


再來就是驗證帳戶的ashx,放在/Tools/CheckAccountDuplicate.ashx:
public void ProcessRequest(HttpContext context)
{
    string nn = context.Request.QueryString["nn"];
    NWDB.NWDB mwdb = new NWDB.NWDB();
    NWDB.ImplImember checkMember = new NWDB.ImplImember(mwdb.Connection);
    mwdb.SetMember(checkMember);
    bool result = mwdb.CheckMemberDuplicate(nn);
    string ans = "";
    if (result)
        ans = "t";
    else
        ans = "f";
    context.Response.Write(ans);
}
這樣就完成第2步啦~!



最後就是網頁端的撰寫
這個加入會員的網頁在之前的文章就寫過,可以前往參考
這邊就只補上需要加入的程式碼:

$(document).ready(function () {

    //blur,當id為Account改變焦點時
    $("#Account").blur(function () {
        if ($("#Account").val() == "") {
            $("#AccountCheckResult").text("");
            return;
        }
        var checkaccount = $.param({ nn: $("#Account").val() });
        $.get("/Tools/CheckAccountDuplicate.ashx"
                , checkaccount
                , function (xx) {
                    if (xx == "t") 
                        $("#AccountCheckResult").text("帳號已被注冊").css("color","red");
                    else
                        $("#AccountCheckResult").text("帳號可以使用").css("color","blue");
                          
                });
    });

});

function checkForm() {
    var msg = "";
    if ($("#AccountCheckResult").text() == "帳號已被注冊")
        msg += "* 請注冊別的帳號";

    if (msg != "") {
        alert(msg);
        return false;
    }
    else {
        $("#form1").submit();
    }
});


如此就大功告成啦!!!
這篇寫得好累~

留言

熱門文章