使用者定義函數和預存程序
透過 ADOMD.NET 伺服器物件,您可以為與中繼資料及伺服器資料互動的 Microsoft SQL Server Analysis Services,建立使用者定義函數 (UDF) 或是預存程序。這些同處理序 (In-Process) 方法是透過「多維度運算式」(Multidimensional Expressions,MDX) 或「資料採礦延伸模組」(Data Mining Extensions,DMX) 陳述式來呼叫,以提供附加功能,並不會有與網路通訊關聯的延遲。
UDF 範例
UDF 是一種可以在 MDX 或 DMX 陳述式的內容中呼叫的方法,可以使用任何數目的參數,並且可以傳回任何類型的資料。
使用 MDX 建立的 UDF 類似於為 DMX 建立的 UDF。主要的差異在於 Context 物件的某些屬性 (例如 CurrentCube 與 CurrentMiningModel 屬性),只能供一個指令碼語言或是其他指令碼語言使用。
下列範例示範如何使用 UDF 傳回節點描述、篩選 Tuple 以及將篩選套用至 Tuple。
傳回節點描述
下列範例會建立 UDF,以傳回指定節點的節點描述。UDF 會使用其執行所在的目前內容,並使用 DMX FROM 子句,從目前的採礦模型擷取節點。
public string GetNodeDescription(string nodeUniqueName)
{
return Context.CurrentMiningModel.GetNodeFromUniqueName(nodeUniqueName).Description;
}
一旦部署,就可以透過下列 DMX 運算式來呼叫上述 UDF 範例,這將可擷取最有可能的預測節點。描述包含構成預測節點的條件資訊。
select Cluster(), SampleAssembly.GetNodeDescription( PredictNodeId(Cluster()) ) FROM [Customer Clusters]
傳回 Tuple
下列範例使用集合和傳回計數,以及從集合隨機擷取 Tuple,以傳回最後的子集:
public Set RandomSample(Set set, int returnCount)
{
//Return the original set if there are fewer tuples
//in the set than the number requested.
if (set.Tuples.Count <= returnCount)
return set;
System.Random r = new System.Random();
SetBuilder returnSet = new SetBuilder();
//Retrieve random tuples until the return set is filled.
int i = set.Tuples.Count;
foreach (Tuple t in set.Tuples)
{
if (r.Next(i) < returnCount)
{
returnCount--;
returnSet.Add(t);
}
i--;
//Stop the loop if we have enough tuples.
if (returnCount == 0)
break;
}
return returnSet.ToSet();
}
在下列 MDX 範例中會呼叫上述範例。在此 MDX 範例中,會從 Adventure Works 資料庫中,擷取五個隨機的州或是省份。
SELECT SampleAssembly.RandomSample([Geography].[State-Province].Members, 5) on ROWS,
[Date].[Calendar].[Calendar Year] on COLUMNS
FROM [Adventure Works]
WHERE [Measures].[Reseller Freight Cost]
將篩選套用至 Tuple
在下列範例中,UDF 是定義成使用集合,並使用 Expression 物件,將篩選套用至集合中的每個 Tuple。任何符合篩選的 Tuple 都將加入傳回的集合。
public static Set FilterSet(Set set, String filterExpression)
{
Expression expr = new Expression(filterExpression);
SetBuilder resultSetBuilder = new SetBuilder();
foreach (Tuple tuple in set)
{
if ((bool)(expr.Calculate(tuple)))
{
resultSetBuilder.Add(tuple);
}
}
return resultSetBuilder.ToSet();
}
在下列 MDX 範例中會呼叫上述範例,以便將集合篩選成以 'A' 開頭的城市名稱。
Select Measures.Members on Rows,
SampleAssembly.FilterSet([Customer].[Customer Geography].[City], "[Customer].[Customer Geography].[City].CurrentMember.Name < 'B'") on Columns
From [Adventure Works]
預存程序範例
在下列範例中,以 MDX 為基礎的預存程序使用 AMO 為「網際網路銷售」建立資料分割 (若有需要的話)。
public static void CreateInternetSalesMeasureGroupPartitions()
{
//Check the current state of the data warehouse and
//create partitions with AMO if necessary
#region Retrieve order date of last sales transaction
// Open a connection to the data warehouse
// TODO: Change the first string parameter to reflect the right server\instance.
SqlConnection conn = new SqlConnection(string.Format("data source={0};initial catalog={1};Integrated Security=SSPI", "server\\instance", Context.CurrentDatabaseName));
conn.Open();
// Create a command
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
// Get the order date key of the last internet sale
int lastInternetSaleDateKey = 0;
cmd.CommandText = "select max(OrderDateKey) from FactInternetSales";
lastInternetSaleDateKey = (int)cmd.ExecuteScalar();
// Get the order date key of the last reseller sale
int lastResellerSaleDateKey = 0;
cmd.CommandText = "select max(OrderDateKey) from FactResellerSales";
lastResellerSaleDateKey = (int)cmd.ExecuteScalar();
#endregion
#region Create partitions
// Connect to the calling session
Server svr = new Server();
svr.Connect("*");
// Get the Adventure Works cube
Database db = svr.Databases.GetByName(Context.CurrentDatabaseName);
Cube cube = db.Cubes[0];
MeasureGroup mg;
int maxOrderDateKey;
mg = cube.MeasureGroups.GetByName("Internet Sales");
maxOrderDateKey = 0;
foreach (Partition part in mg.Partitions)
{
maxOrderDateKey = Math.Max(maxOrderDateKey, Convert.ToInt32(
part.Annotations.Find("LastOrderDateKey").Value.Value,
System.Globalization.CultureInfo.InvariantCulture));
}
if (maxOrderDateKey < lastInternetSaleDateKey)
{
Partition part = mg.Partitions.Add("Internet_Sales_"
+ lastInternetSaleDateKey);
part.StorageMode = StorageMode.Molap;
part.Source = new QueryBinding(db.DataSources[0].ID,
"SELECT * FROM [dbo].[FactInternetSales] WHERE OrderDateKey > '"
+ maxOrderDateKey + "' and OrderDateKey <= '" + lastInternetSaleDateKey + "'");
part.Annotations.Add("LastOrderDateKey", Convert.ToString(lastInternetSaleDateKey,
System.Globalization.CultureInfo.InvariantCulture));
part.Update();
part.Process();
}
svr.Disconnect();
#endregion
}