假如你有一個購物類的網站,那麼你如何給你的客戶來推薦產品呢?這個功能在很多電商類網站都有,那麼,通過SQL Server Analysis Services的資料採礦功能,你也可以輕鬆的來構建類似的功能。
將分為三個部分來示範如何?這個功能。
1.構建採礦模型
2.為採礦模型編寫服務介面
3.開發簡單的前端應用
此篇在上一篇已經構建好採礦模型的基礎之上,介紹如何構建服務介面。
編寫服務介面的方法很多,比如使用WCF。為了簡便,這裡直接使用ASP.NET Web Services。
將採礦模型的具體查詢的實現部分寫到Web服務代碼中,主要是考慮到代碼分層降低耦合性。另外這部分邏輯通過服務的方式來暴露介面,可以方便其它任何平台來進行調用,比如ASP.NET, Winform, WPF或者其它基於java的技術架構等。Web服務最主要的部分是XML,一個服務介面往往就是一個URL地址,用戶端程式通過向這個地址發送xml請求的方式,來擷取服務端代碼的響應,結果再以xml的方式返回回來。那麼既然來回通訊的都是xml資料,是否意味這還要手動寫代碼來序列化和還原序列化xml資料呢?這裡面又涉及到一個SOAP的概念,這是一個在10年前很火的概念,簡易物件存取通訊協定 (SOAP)。通過這個SOAP協議,用戶端程式可以知道要訪問一個Web服務,應該發送什麼樣的xml資料,以及收到服務端xml的資料之後,本地再如何解析這些資料。基於這樣一個方式,Visual Studio中,當你引用一個服務的時候,它就會根據這個協議,在你本地產生若干代理類,這樣在你調用遠端一個Web服務的時候,你就會感覺像是在調用本地裡的一個類的方法一樣方便。
筆者註:如果你用Winform和ASP.NET等,那麼你也可以選擇直接在代碼裡訪問採礦模型的資料,但是如果是其它平台,比如Win 8 App, silverlight和flash等,它們是無法直接和資料來源進行通訊的,所以只能通過服務的方法來訪問。
本篇就是要編寫這樣一個服務介面,這個服務接受客戶已經購買的商品列表資訊,然後根據這些資訊來向使用者推薦其它商品。
服務的核心邏輯是根據傳送過來的商品列表,來動態去拼DMX語句。在上一篇中提到的那個DMX語句,這裡主要以它為"模版"。
SELECT FLATTENED
PredictAssociation([Association].[v Assoc Seq Line Items],INCLUDE_STATISTICS,3)
FROM
[Association]
NATURAL PREDICTION JOIN
(
SELECT (SELECT 'Touring Tire' AS [Model]
UNION
SELECT 'Touring Tire Tube' AS [Model]
) AS [v Assoc Seq Line Items]) AS t
根據上一篇的講解,我們知道需要變化的就是SELECT UNION SELECT的部分,一條商品對應一個SELECT。
還有一個需要介紹的東西是ADOMD.NET,這個名字你看上去可能感覺有些面熟,沒錯,你肯定用過ADO.NET,還記得經典方式操作資料庫的步驟嗎?建立Connection, Command然後DataReader或者其它方式來接收資料。ADOMD.NET就是專門用來訪問分析服務用的,由於它跟ADO.NET一樣都整合自同一介面,所以你可以找到熟悉的Connection和Command對象,而接收對象的除了DataReader外,還有跟DataSet相對應的CellSet對象。
傳統的分析服務是包含多維模型和資料採礦的,所以在ADOMD.NET下,可以拋MDX(查Cube用的)和DMX(查採礦模型用的)。這裡我們用的資料提供者就是ADOMD.NET。
確認好以上邏輯之後,我們開始構建Web服務。
這裡我們使用Visual Studio 2012來編寫服務。跟上一篇不同,上一篇為了編寫一個SQL Server 2012的分析服務項目,我們用的是SQL Server Data Tools,這個實際上就是Visual Studio 2010的一個Shell。而那個地方為什麼用的版本是2010而不是2012?這裡面有一個SQL Server和Visual Studio版本的一個對應的關係。
SQL Server版本 |
對應的Visual Studio Shell版本 |
2000 |
無 |
2005 |
2005 |
2008 |
2008 |
2012 |
2010 |
2012的下一個版本 |
2012 |
可以看到主要還是根據兩個產品系列的版本發布有關係。所以這裡就有一個地方需要留意,如果你的機器上同時安裝了Visual Studio 2012和SQL Server 2012,那麼當你開啟一個類似上一篇中建立的分析服務項目的時候,不要預設雙擊開啟專案檔,因為系統會用Visual Studio 2012 (不是應該與其對應的2010)來開啟你的項目,然後提示你將項目升級到2012。不用想,對應Visual Studio 2012 Shell的SQL Server版本還沒發布呢,所以即使升級了最後也一定是失敗。
下面言歸正傳,開啟Visual Studio 2012。點擊功能表列FILE->New Project。
項目類型選擇ASP.NET Empty Web Application。
點擊OK建立一個新ASP.NET項目。
在Solution Explorer中,右鍵項目名稱,點Add->New Item。
在Add New Item中,選擇Web Service。然後點Add。
然後可以看到系統自動產生的測試用的服務代碼。
下面首先添加ADOMD.NET引用。右鍵項目目錄,選擇Add Reference。
ADOMD.NET組件不會預設出現在這裡。需要點擊Browse手動去找。
通常ADOMD.NET組件的位置是位於這個目錄下:
C:\Program Files\Microsoft.NET\ADOMD.NET\110
找到Microsoft.AnalysisServices.AdomdClient.dll,點OK。
可以看到ADOMD.NET組件已經被添加到引用目錄下。
然後,回到Web服務代碼介面,在代碼中using這個庫的引用。
然後為服務編寫代碼,首先定義一個類,服務的結果將以這個類的結構返回。
public class ModelResult
{
public string ModelName { get; set; }
public double Support { get; set; }
public double Probility { get; set; }
}
定義好這個類之後,再編寫服務代碼,這裡直接貼出來:
[WebMethod]
public List<ModelResult> GetModelResult(List<string> ModelList)
{
List<ModelResult> result = new List<ModelResult>();
bool FirstOne = true;
//Build DMX query
StringBuilder sb = new StringBuilder();
sb.AppendLine("SELECT FLATTENED");
sb.AppendLine("PredictAssociation([Association].[v Assoc Seq Line Items],INCLUDE_STATISTICS,3)");
sb.AppendLine("FROM");
sb.AppendLine("[Association]");
sb.AppendLine("NATURAL PREDICTION JOIN");
sb.AppendLine("(");
foreach (string item in ModelList)
{
if (FirstOne == true)
{
sb.AppendLine("SELECT (SELECT '" + item + "' AS [Model]");
FirstOne = false;
}
else
{
sb.AppendLine("UNION");
sb.AppendLine("SELECT '" + item + "' AS [Model]");
}
}
sb.AppendLine(") AS [v Assoc Seq Line Items]) AS t");
AdomdConnection conn = new AdomdConnection();
conn.ConnectionString = "Provider=MSOLAP.3;Integrated Security=SSPI;Persist Security Info=True;Initial Catalog=MultidimensionalProject1;Data Source=.";
conn.Open();
AdomdCommand comm = new AdomdCommand(sb.ToString(), conn);
AdomdDataReader dr = comm.ExecuteReader();
//Read result
while (dr.Read())
{
ModelResult mr = new ModelResult();
mr.ModelName = dr[0].ToString();
mr.Support = Convert.ToDouble(dr[1]);
mr.Probility = Convert.ToDouble(dr[2]);
result.Add(mr);
}
conn.Close();
return result;
}
留意貼出的這段代碼第一行,有一個[WebMethod],Web服務的方法跟一個類的傳統方法區別就在這裡,只有在方法前面打上這個標記才會被系統認為是一個Web服務方法發布出去。
代碼中先根據上一篇提到的DMX語句的查詢"模版",中簡通過一個foreach迴圈來動態構建SELECT UNION SELECT部分。最後通過Connection和Command對象以及DataReader方法來讀取結果,並且把其載入到類裡。
然後,為了方便測試,再加一個測試服務方法:
[WebMethod]
public List<ModelResult> GetModelResultTest(string ModelSingle)
{
List<string> ModelList = new List<string>();
ModelList.Add(ModelSingle);
return GetModelResult(ModelList);
}
這個方法實際上還是調用了剛才建立的服務方法,只不過它只傳遞了一個商品過來,在這裡打包成一個List後丟掉那個方法裡。
這樣,在ASP.NET內建的服務瀏覽介面中就可以測試我們剛才編寫的方法了。右鍵asmx檔案點View in Browser。
然後可以看到系統自動為服務建立的簡單測試頁面。
這裡點擊GetModelResultTest方法。
在參數值中輸入'Touring Tire',點"調用"。
最後,就可以看到服務返回的結果資訊。資訊的格式是通過xml的,你無需去解析它,通過前面提到的SOAP協議,系統會為你建立相應的本地代理類。
至此,為採礦模型編寫的服務層代碼就編寫完畢了。下一篇將建立一個應用程式來調用這個服務從而實現一個簡單的商品推薦功能。