C# AMO-使用foreach循环基于SQL查找动态删除分区

C# AMO-使用foreach循环基于SQL查找动态删除分区,c#,ssis,ssas,C#,Ssis,Ssas,我正在尝试构建一个SSIS脚本任务,该任务将根据数据库视图中的分区列表检查SSAS多维数据集上的分区名称。如果分区存在但不在列表中,则会删除该分区,否则会对其进行处理 该脚本在将删除分区的情况下似乎可以工作,但它似乎无法继续循环,并在删除时生成枚举错误,如下所示: 仅在尝试处理时运行脚本(即,rowCount==1和pt.process(),不带else条件)工作正常,并且完成时没有错误。似乎我无法在循环通过分区的集合时删除分区。如果在SQL查找表中找到这些分区,我将非常感谢提供如何删除这些分

我正在尝试构建一个SSIS脚本任务,该任务将根据数据库视图中的分区列表检查SSAS多维数据集上的分区名称。如果分区存在但不在列表中,则会删除该分区,否则会对其进行处理

该脚本在将删除分区的情况下似乎可以工作,但它似乎无法继续循环,并在删除时生成枚举错误,如下所示:

仅在尝试处理时运行脚本(即,
rowCount==1
pt.process()
,不带
else
条件)工作正常,并且完成时没有错误。似乎我无法在循环通过分区的集合时删除分区。如果在SQL查找表中找到这些分区,我将非常感谢提供如何删除这些分区的指针

   public void Main()
    {
        try
        {
            String Server = Dts.Variables["User::Connection"].Value.ToString();
            String Cube = "CubeName";
            String conn = "Provider=MSOLAP;Data Source=" + Server + ";";


            Server MDXServer = new Server();
            MDXServer.Connect(conn);

            foreach (Database db in MDXServer.Databases)
            {
                foreach (Cube cb in db.Cubes)
                {
                    if (cb.Name == Cube)
                    {
                        foreach (MeasureGroup mg in cb.MeasureGroups)
                        {
                            foreach (Partition pt in mg.Partitions)
                            {
                                string PartName = (pt.Name.ToString());

                                //Create SQL query to reference the parition view and check row count when partition name used in predicate:
                                string sqlString = "SELECT COUNT(*) FROM [dim].[Partitions] WHERE [FinWeek] = @pt;";
                                // Open DB connection:
                                ConnectionManager cm;
                                cm = Dts.Connections["FIP_Server_Alias"];
                                SqlConnection connection = (SqlConnection)cm.AcquireConnection(Dts.Transaction);
                                // Link the query and the connection string together as a command
                                SqlCommand cmd = new SqlCommand(sqlString, connection);
                                // Add a value to the parameter in the SQL query
                                cmd.Parameters.AddWithValue("@pt", PartName);


                                // Activate reader to read the resulting data set from the query
                                SqlDataReader reader = cmd.ExecuteReader();

                                while (reader.Read()) //while loop performs an action whilst the reader is open
                                {
                                    // Put the second result of query (0 woudl be first) into a string variable in the script task
                                    string rowCount = reader[0].ToString();

                                    //if the partition exists but is not in the database dim.Partitions view, drop from collection.
                                    if (rowCount == "0")
                                    {
                                        pt.Drop();
                                    }
                                }
                                //End the read loop
                                reader.Close();

                            }
                        }
                    }
                }
            }
        }



        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }


        Dts.TaskResult = (int)ScriptResults.Success;
    }

它告诉您在循环时不能修改正在循环的集合

因此,解决这个问题的一种方法是在
foreach
循环中时不要删除分区。而是将其添加到数组或字符串生成器或您选择的其他新创建的集合中


然后在
foreach
循环之后,循环新创建的集合,并删除与集合的每个成员关联的分区。

它告诉您,在循环过程中不能修改正在循环的集合

因此,解决这个问题的一种方法是在
foreach
循环中时不要删除分区。而是将其添加到数组或字符串生成器或您选择的其他新创建的集合中


然后在
foreach
循环之后,循环新创建的集合,并删除与集合的每个成员关联的分区。

下面是我通过Tab Alleman的steer找到的将其添加到集合的解决方案。在我完成对服务器本身的查询之后,分区列表在第二个
foreach
循环中循环。我创建了一个新的
XmlaWarningCollection
,并从中删除,它似乎可以维护连接。它会删除数据库视图中未列出的所有分区

有关更多帮助,请访问此Microsoft博客:

public void Main()
{
尝试
{
String Server=Dts.Variables[“User::Connection”].Value.ToString();
String Cube=“TestCube”;
String conn=“Provider=MSOLAP;数据源=“+Server+”;”;
Server MDXServer=new Server();
MDXServer.Connect(conn);
//添加集合以包含要删除的分区
列表分区=新列表();
foreach(MDXServer.Databases中的数据库db)
{
foreach(db.Cubes中的多维数据集cb)
{
if(cb.Name==Cube)
{
foreach(cb中的测量组mg.测量组)
{
foreach(以mg.分区表示的分区pt)
{
字符串PartName=(pt.Name.ToString());
//创建SQL查询以引用分区视图,并在谓词中使用分区名称时检查行数:
string sqlString=“从[dim].[Partitions]中选择计数(*),其中[Partition]=@pt;”;
//打开数据库连接:
连接管理器cm;
cm=Dts.Connections[“服务器别名”];
SqlConnection连接=(SqlConnection)cm.AcquireConnection(Dts.Transaction);
//将查询和连接字符串作为命令链接在一起
SqlCommand cmd=新的SqlCommand(sqlString,connection);
//向SQL查询中的参数添加值
cmd.Parameters.AddWithValue(“@pt”,零件名);
//激活读卡器以从查询中读取结果数据集
SqlDataReader=cmd.ExecuteReader();
while(reader.Read())//while循环在读卡器打开时执行操作
{
//将查询结果放入脚本任务中的字符串变量中
字符串行数=读取器[0]。ToString();
//如果分区存在但不在数据库dim.Partitions视图中,请从集合中删除。
如果(行计数=“0”)
{
添加(pt);
}
}
//结束读取循环
reader.Close();
}
}
}
}
}
//循环遍历在上述foreach循环中创建的集合,并从服务器中删除其中的分区。
foreach(分区中的分区dropPartition)
{
XmlaWarningCollection warningColln=新的XmlaWarningCollection();
dropPartition.Drop(DropOptions.Default,warningColln);
}
Dts.TaskResult=(int)ScriptResults.Success;
}
捕获(例外情况除外)
{
//捕获错误并将错误返回到包以进行日志记录
Dts.Events.FireError(0,“脚本任务错误:”,例如Message+“\r”+ex.StackTrace,String.Empty,0);
Dts.TaskResult=(int)ScriptResults.Failure;
}
}

这是我用Tab Alleman's steer找到的将其添加到coll中的解决方案
    public void Main()
    {
        try
        {
            String Server = Dts.Variables["User::Connection"].Value.ToString();
            String Cube = "TestCube";
            String conn = "Provider=MSOLAP;Data Source=" + Server + ";";


            Server MDXServer = new Server();
            MDXServer.Connect(conn);

            //Add collection to contain partitions to be dropped
            List<Partition> partitions = new List<Partition>();

            foreach (Database db in MDXServer.Databases)
            {
                foreach (Cube cb in db.Cubes)
                {
                    if (cb.Name == Cube)
                    {
                        foreach (MeasureGroup mg in cb.MeasureGroups)
                        {
                            foreach (Partition pt in mg.Partitions)
                            {
                                string PartName = (pt.Name.ToString());

                                //Create SQL query to reference the parition view and check row count when partition name used in predicate:
                                string sqlString = "SELECT COUNT(*) FROM [dim].[Partitions] WHERE [Partition] = @pt;";
                                // Open DB connection:
                                ConnectionManager cm;
                                cm = Dts.Connections["Server_Alias"];
                                SqlConnection connection = (SqlConnection)cm.AcquireConnection(Dts.Transaction);
                                // Link the query and the connection string together as a command
                                SqlCommand cmd = new SqlCommand(sqlString, connection);
                                // Add a value to the parameter in the SQL query
                                cmd.Parameters.AddWithValue("@pt", PartName);

                                // Activate reader to read the resulting data set from the query
                                SqlDataReader reader = cmd.ExecuteReader();

                                while (reader.Read()) //while loop performs an action whilst the reader is open
                                {
                                    // Put the result of query into a string variable in the script task
                                    string rowCount = reader[0].ToString();

                                    //if the partition exists but is not in the database dim.Partitions view, drop from collection.
                                    if (rowCount == "0")
                                    {
                                        partitions.Add(pt);
                                    }
                                }
                                //End the read loop
                                reader.Close();
                                }
                        }
                    }
                }
            }
            //Loop through the collection created in the above foreach loop and drop the partitions in it from the server.
            foreach (Partition dropPartition in partitions)
            {
                XmlaWarningCollection warningColln = new XmlaWarningCollection();
                dropPartition.Drop(DropOptions.Default, warningColln);
            }
         Dts.TaskResult = (int)ScriptResults.Success;
        }



          catch (Exception ex)
        {
            //catch error and return error to package for logging 
            Dts.Events.FireError(0, "Script task error: ", ex.Message + "\r" + ex.StackTrace, String.Empty, 0);
            Dts.TaskResult = (int)ScriptResults.Failure;  
        }



    }