2015年9月7日 星期一

Codova + SQLite

 SQLite 是免費資料庫軟體,也可以跨平台(windows/Linux) ,當然手機也內建,但是和NOSQL概念不同喔,仍是關聯式資料庫,不少codova 會結合SQLite做一些APP的應用,以下範例教學剛好有使用到SQLite 也提供大家一些參考

一、建立SQLite 的函式庫 :寫成獨立的核心SQL元件

var db;
var sqlList = {
    openDB:function myfunction(dbName) {
        db = window.openDatabase("Database", "1.0", dbName, 1000);
        return db;
    },
    executeSQL: function myfunction(db, sqlcommand,  returnSuccessHandler) {
        //宣告 returnSuccessHandler 函式
       db.transaction(selectDBTransactionSuccessHandler,
               errorHandler, function () { });
        function selectDBTransactionSuccessHandler(sqlTransaction) {
            sqlTransaction.executeSql(sqlcommand, [], successHandler, errorHandler);
        };
        function successHandler(sqlTransaction, sqlResultSet) {
//呼叫 returnSuccessHandler 函式 回傳結果
            returnSuccessHandler(sqlResultSet.rows);
        }
        function errorHandler(errorCode) {
            console.log("executeSQL" + " sql: error");
            console.log(errorCode.err);
        };
    },
    executeNonQuery: function executeQuery(db, sqlcommand) {
        db.transaction(function (tx) {
            tx.executeSql(sqlcommand, [], function () { }, errorHandler);
        }, function errorCB(err) {
            alert("error");
            console.warn("Error processing SQL: " + err.code);
        }, function () {
        });

        function errorHandler(err) {
            alert("無法執行sql指令!" +sqlcommand + "錯誤碼" + err.code);
        }
    },
    executeNonQueryWithID: function (db, sqlcommand, id) {
        db.transaction(function (tx) {
            tx.executeSql(sqlcommand, [id], function () {
            });
        }, function errorCB(err) {
            alert("error");
            console.warn("Error processing SQL: " + err.code);
        }, function () {
        });
    }
};

executeSQL: function myfunction(db, sqlcommand,  returnSuccessHandler):
要將SQLite執行的結果回傳,需要有一個函式負責接收回傳值,所以returnSuccessHandler 是函數名稱,而非變數名稱,透過此函式回傳結果。

二、新增、刪除、修改等操作

新增資料庫
  var db =sqlList.openDB("clinicDatabase"); //開啟資料表

新增資料表
sqlList.executeNonQuery(db, "CREATE TABLE  IF NOT EXISTS  clinics (id INTEGER PRIMARY KEY AUTOINCREMENT, clinicName TEXT, clinicIP TEXT, user TEXT, password TEXT)");

刪除資料表
sqlList.executeNonQuery(db, "DROP  TABLE  IF EXISTS  clinics ");

新增資料
var sqlValue = "INSERT INTO clinics (clinicName,clinicIP,user,password) VALUES('" + clinicName + "'," + "'" + clinicIP + "','" + user + "','" + password + "')";

刪除資料
  sqlList.executeNonQueryWithID(db, "delete from clinics where id=?", id);

執行SQL的查詢語法
var db =sqlList.openDB("clinicDatabase"); //開啟資料表
   sqlList.executeSQL(db, "select * from clinics",  function (readData) {
       //查詢的資料回傳值… 
        $("#settingPage_clinicName").val(readData.item(0).clinicName);
         $("#settingPage_clinicIP").val(readData.item(0).clinicIP);
         $("#settingPage_user").val(readData.item(0).user);
         $("#settingPage_password").val(readData.item(0).password);
});
   

    將SQLite的執行SQL的共同函式變成物件,程式是不是變得簡潔許多呢? 因為在codova 呼叫sqlLite 會以非同步結果回應傳回值,所以要在function () {} 內才能接受回覆的值,希望這對大家有所幫助~ 感謝各位蒞臨。 

2015年9月2日 星期三

Angular + Asp.net MVC 多檔上傳

自從Html5 增加file的功能後,檔案上傳的功能簡化不少,剛好有案子正好需要上傳圖片,所以可以示範如何在Angular 上傳檔案後,再經由MVC後端接收圖片的教學,最後又透過Angular的特殊功能,把多張圖片展示在列表上。

一、HTML5 的語法
瀏覽器已經將上傳檔案的功能內建化,所以讓後端處理細節簡化不少,
加上multiple 允許多個檔案上傳,預設只能單檔上傳,所以multiple 屬性要加上

<input type="file" name="multipleFiles" multiple />

二、Angular的語法

傳統的網頁是經由post把網頁內的form 資訊往server後端傳遞,但是
Ajax已經是網頁必備的功能,只將部份訊息往後端傳遞,所以angular中宣告formData變數就是要把前端的訊息集中起來,再呼叫$http.postformData 送給asp.net MVC controller

Angular 有很多參數和函數,作者沒有深入研究,因為$http.post是非常方便的工具,$http Angular和遠端http Server 溝通的核心

var formData = new FormData();//傳送到後端的資訊
      //上傳多張圖片
                $.each($("input[name='multipleFiles']"), function (i, obj) {
                    $.each(obj.files, function (j, file) {                       
                        formData.append('photo[' + j + ']', file);  //以陣列方式傳遞多檔圖片或檔案
                    })
                });        
$http.post(‘../Test/AddReleaseBug’, formData, {
   headers: { 'Content-Type': undefined }
 }).then(function (res) {
 alert("儲存成功");
}));

  
三、Asp.net MVC

Asp.net MVC為了要接收來自前端的上傳的圖片,所以宣告
HttpPostedFileBase陣列的型態去接收檔案,就可以接收多個檔案,為了隔離網頁的呈現層(asp.net mvc)和企業邏輯,所以增加實體層entityTest 負責資料DB的取得,如果網頁架構較大時,可以增加控制層,負責更細節的邏輯控制,再由控制層再呼叫實體層,這就是早期的三層式架構(MVC)模式。

Asp.net Controller
      [HttpPost]
        public async Task<bool> AddReleaseBug( IEnumerable<HttpPostedFileBase>[] photo)
        {         
            string path = "bugFile";
            string strMultiFiles = "";         
           if (photo != null)
                {
                    foreach (IEnumerable<HttpPostedFileBase> uploadImage in photo)
                    {
                        strMultiFiles += await entityTestObj.fileUpload(uploadImage, path) + ",";
                    }
                    strMultiFiles = strMultiFiles.Substring(0, strMultiFiles.Length - 1);
                }
        }

實體層:
FileUpload 負責把檔案儲存到指定的路徑中,並把檔名回傳
  public async Task<string> fileUpload(IEnumerable<HttpPostedFileBase> addDownloadFile, string path)
        {
            try
            {
                var fileName = "";
                var httpPath = HttpContext.Current.Server.MapPath("~/" + path);
                Directory.CreateDirectory(httpPath); //路徑不存在自已建立
                if (addDownloadFile.Count() > 0)
                {
                    foreach (HttpPostedFileBase file in addDownloadFile)
                    {
                        fileName += Path.GetFileName(file.FileName) + ",";
                        var pathFileName = Path.Combine(httpPath, file.FileName);
                        file.SaveAs(pathFileName);
                    }
                    fileName = fileName.Substring(0, fileName.Length - 1);                  
                }
                return fileName;
            }
            catch (Exception ex)
            {
                writeObj.writeToFile("ManageFileVersion_" + DateTime.Now.ToString("yyyyMMdd"), HttpContext.Current.Server.MapPath("~"), "fileUpload error: " + ex.Message);
                throw new Exception(ex.Message);
            }
}

示範: photo陣列集中共有3個檔案上傳

四、Angular如何split(“,”)

有點偏離主題,因為延續多檔上傳的功能,我將多檔案名稱儲存在同一欄位
中,並以『,』隔離,所以如果要在前端呈現多個圖片時,要以逗號隔離,但是Angular 有支援split的功能,所以這是一個好用的工具喔。

<font color="blue">圖片</font>:<br />
<a href="~/bugFile/{{::bug.bugDocumentFile.split(',')[0] }}" arget="_blank">{{::bug.bugDocumentFile.split(',')[0] }}</a>
<a href="~/bugFile/{{::bug.bugDocumentFile.split(',')[1] }}" arget="_blank">{{::bug.bugDocumentFile.split(',')[1] }}</a>
<a href="~/bugFile/{{::bug.bugDocumentFile.split(',')[2] }}" arget="_blank">{{::bug.bugDocumentFile.split(',')[2] }}</a>
<a href="~/bugFile/{{::bug.bugDocumentFile.split(',')[3] }}" arget="_blank">{{::bug.bugDocumentFile.split(',')[3] }}</a>
<a href="~/bugFile/{{::bug.bugDocumentFile.split(',')[4] }}" arget="_blank">{{::bug.bugDocumentFile.split(',')[4] }}</a>     

如果以上有更好的建議的話,歡迎多多留言,希望在這共同的平台上面,大
家可以共同教學相長。

五、文獻參考
1.    https://docs.angularjs.org/api/ng/service/$http