Funciones definidas por el usuario y procedimientos almacenados
Con ADOMD.NET de servidor, puede crear funciones definidas por el usuario (UDF) o procedimientos almacenados para Microsoft SQL Server Analysis Services que interactúan con metadatos y datos del servidor. Se llama a estos métodos incrustados a través de instrucciones de expresiones multidimensionales (MDX) o extensiones de minería de datos (DMX) para proporcionar una funcionalidad adicional sin las latencias asoció a las comunicaciones de red.
Ejemplos de UDF
UDF es un método al que se puede llamar en el contexto de una instrucción MDX o DMX, admite cualquier número de parámetros y devuelve cualquier tipo de datos.
Un UDF que se crea mediante MDX es similar al que se crea para DMX. La principal diferencia es que ciertas propiedades del objeto Microsoft.AnalysisServices.AdomdServer.Context, como las propiedades Microsoft.AnalysisServices.AdomdServer.Context.CurrentCube y Microsoft.AnalysisServices.AdomdServer.Context.CurrentMiningModel, solo están disponibles para un lenguaje de scripting u otro.
En los ejemplos siguientes se muestra cómo usar un método UDF para devolver una descripción del nodo, filtrar tuplas y aplican un filtro a una tupla.
Devolver una descripción del nodo.
En el ejemplo siguiente se crea un UDF que devuelve la descripción del nodo para un nodo especificado. UDF usa el contexto actual en el que se ejecuta y utiliza una cláusula DMX FROM para recuperar el nodo del modelo de minería actual.
public string GetNodeDescription(string nodeUniqueName)
{
return Context.CurrentMiningModel.GetNodeFromUniqueName(nodeUniqueName).Description;
}
Una vez implementado, la expresión DMX siguiente puede llamar al ejemplo UDF anterior, que recupera el nodo de predicción más probable. La descripción contiene información que describe las condiciones que constituyen el nodo de predicción.
select Cluster(), SampleAssembly.GetNodeDescription( PredictNodeId(Cluster()) ) FROM [Customer Clusters]
Devolver tuplas
En el ejemplo siguiente se establece un conjunto y un recuento del retorno, y se recuperan de forma aleatoria las tuplas del conjunto, devolviendo un subconjunto final:
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();
}
Se llama al ejemplo anterior en el ejemplo MDX siguiente. En este ejemplo MDX, se recuperan cinco estados o provincias aleatorios de la base de datos 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]
Aplicar un filtro a una tupla
En el ejemplo siguiente, se define un UDF para que establezca un conjunto y aplique un filtro a cada tupla en el conjunto mediante el objeto Expression. Cualquier tupla que cumpla el filtro se agregará a un conjunto que se devuelve.
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();
}
En el siguiente ejemplo MDX se llama al ejemplo anterior, que filtra el conjunto por ciudades con nombres que empiezan por 'A.'
Select Measures.Members on Rows,
SampleAssembly.FilterSet([Customer].[Customer Geography].[City], "[Customer].[Customer Geography].[City].CurrentMember.Name < 'B'") on Columns
From [Adventure Works]
Ejemplo de procedimiento almacenado
En el ejemplo siguiente, un procedimiento almacenado basado en MDX utiliza AMO para crear particiones para Internet Sales si es necesario.
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
}