简体   繁体   中英

C# script in SSIS package hangs in the middle of data implementation to SQL Server table with no clear error message

I am not a C# expert but I have a C# script in a SSIS script task that connects to a SQL Server table with user and password credentials. The script converts geographical data from WGS to Lambert.

It works fine in the beginning, but the script stops implementing data in about 30 minutes without a clear error message, I get a pop up with this message

an exception has been thrown by the target of an invocation

à System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
à System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
à System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
à System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
à Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTATaskScriptingEngine.ExecuteScript()

I tried deploying the package to SQL Server and it stops working in the middle too.

Thank you in advance

here is the script

#region Help:  Introduction to the script task

#endregion


#region Namespaces
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Text;
#endregion

namespace ST_1e550fb6488d4c91bf7449b1754af4cc
{
    /// <summary>

    /// </summary>
    [Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
    public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
    {
        #region Help:  Using Integration Services variables and parameters in a script
   

        #endregion

        #region Help:  Firing Integration Services events from a script
   
        #endregion

        #region Help:  Using Integration Services connection managers in a script

        #endregion


 
        public void Main()
        {
            
          
            string constring = @"Data Source=sqls01-bus.database.windows.net;User ID=*******;password = ******;Initial Catalog=*****;Persist Security Info=True;";
         

            SqlConnection connection = new SqlConnection(constring);

            Dts.TaskResult = (int)ScriptResults.Success;
            using (connection)
            {
                SqlCommand command = new SqlCommand(
                  "SELECT MINX, MINY, ID_ELEMENT FROM SPATIALPOINT  order by ID_ELEMENT;",
                  connection);
                connection.Open();

                SqlDataReader reader = command.ExecuteReader();

                if (reader.HasRows)
                {
                    while (reader.Read())
                    {

                        Point pt = convertToWGS84Deg(double.Parse(reader.GetValue(0).ToString()), double.Parse(reader.GetValue(1).ToString()), Zone.Lambert93);
                        double[] tab = WGS84ToLambert2e(pt.x, pt.y);
                        int idElement = int.Parse(reader.GetValue(2).ToString());
                        insererElementDansLaTableElementComp(pt, constring, idElement, tab, double.Parse(reader.GetValue(0).ToString()), double.Parse(reader.GetValue(1).ToString()));
                    }
                }
                else
                {
                    Console.WriteLine("No rows found.");
                }
                reader.Close();
            }

            //Point pt = convertToWGS84Deg(668832.5384, 6950138.7285, Zone.Lambert93);




        }
        public static double[] WGS84ToLambert2e(double longitude, double latitude)
        {
            // Le système de coordonnées géographiques utilisé est postif vers le Nord et vers l'Est
            var orientation_lat = 'N';
            if (latitude < 0)
            {
                orientation_lat = 'S';
                latitude = -1 * latitude;
            }
            var degree_lat = Math.Truncate(latitude);
            var decPart = latitude - degree_lat;

            var multipliedBy3600 = decPart * 3600;
            var dividedBy60 = multipliedBy3600 / 60.0;
            var minute_lat = Math.Truncate(dividedBy60);
            decPart = dividedBy60 - minute_lat;
            var seconde_lat = decPart * 60;

            // Le système de coordonnées géographiques utilisé est postif vers le Nord et vers l'Est
            var orientation_long = 'E';
            if (longitude < 0)
            {
                orientation_long = 'W';
                longitude = -1 * longitude;
            }
            var degree_long = Math.Truncate(longitude);
            decPart = longitude - degree_long;

            multipliedBy3600 = decPart * 3600;
            dividedBy60 = multipliedBy3600 / 60.0;
            var minute_long = Math.Truncate(dividedBy60);
            decPart = dividedBy60 - minute_long;
            var seconde_long = decPart * 60;

            return WGS84toLambert2e(degree_long, minute_long, seconde_long, orientation_long, degree_lat, minute_lat, seconde_lat, orientation_lat);
        }
        public static double[] WGS84toLambert2e(double d_long, double m_long, double s_long, char orientation_long, double d_lat, double m_lat, double s_lat, char orientation_lat)
        {
            double lambda_w, phi_w;

            /**************************************************************************************************************/
            /**        0) degres-minutes-secondes + orientation (d,m,s,o) -> radian                                           **/
            /**************************************************************************************************************/

            // Pour la longitude
            lambda_w = d_long + m_long / 60 + s_long / 3600;
            if (orientation_long == 'W') lambda_w = -1 * lambda_w; // Le système de coordonnées géographiques utilisé est postif vers le Nord et vers l'Est

            lambda_w = lambda_w * Math.PI / 180;

            // Pour la latitude
            phi_w = d_lat + m_lat / 60 + s_lat / 3600;
            if (orientation_lat == 'S') phi_w = -1 * phi_w;          // Le système de coordonnées géographiques utilisé est postif vers le Nord et vers l'Est

            phi_w = phi_w * Math.PI / 180;

            /**************************************************************************************************************/
            /**        1) coordonnées géographiques WGS84 (phi_w,lambda_w) -> coordonnées cartésiennes WGS84 (X_w,Y_w,Z_w)  **/
            /**************************************************************************************************************/

            // J'ai utilisé 2 formules données par l'IGN dans un de leur document ainsi que deux constantes de 
            // l'ellipsoide de référence du système WGS84 (les deux demi-axes) :

            double a_w = 6378137.0;
            double b_w = 6356752.314;

            // d'où
            double e2_w = (a_w * a_w - b_w * b_w) / (a_w * a_w);

            // et on a la grande normale de l'ellipsoide WGS84
            double N = a_w / Math.Sqrt(1 - e2_w * Math.Pow(Math.Sin(phi_w), 2));

            // ainsi on obtient
            double X_w = N * Math.Cos(phi_w) * Math.Cos(lambda_w);
            double Y_w = N * Math.Cos(phi_w) * Math.Sin(lambda_w);
            double Z_w = N * (1 - e2_w) * Math.Sin(phi_w);

            /**************************************************************************************************************/
            /**        2) coordonnées cartésiennes WGS84 (X_w,Y_w,Z_w) -> coordonnées cartésiennes NTF (X_n,Y_n,Z_n)          **/
            /**************************************************************************************************************/

            // Là il n'y a qu'un translation à effectuer :

            // on a donc
            double dX = 168.0;
            double dY = 60.0;
            double dZ = -320.0;

            // et...
            double X_n = X_w + dX;
            double Y_n = Y_w + dY;
            double Z_n = Z_w + dZ;

            /**************************************************************************************************************/
            /**        3) coordonnées cartésiennes NTF (X_n,Y_n,Z_n) -> coordonnées géographiques NTF (phi_n,lambda_n)      **/
            /**************************************************************************************************************/

            // J'ai utilisé 1 formule donnée par l'IGN toujours dans le même document ainsi que deux constantes de l'ellipsoide 
            // de référence du système NTF, Clarke 1880 :

            double a_n = 6378249.2;
            double b_n = 6356515.0;

            // d'où
            double e2_n = (a_n * a_n - b_n * b_n) / (a_n * a_n);

            // on définit une tolérance de convergence
            double epsilon = Math.Pow(10, -10);

            // puis on amorce une boucle de calcul        
            double p0 = Math.Atan(Z_n / Math.Sqrt(X_n * X_n + Y_n * Y_n) * (1 - (a_n * e2_n) / (Math.Sqrt(X_n * X_n + Y_n * Y_n + Z_n * Z_n))));
            double p1 = Math.Atan((Z_n / Math.Sqrt(X_n * X_n + Y_n * Y_n)) / (1 - (a_n * e2_n * Math.Cos(p0)) / (Math.Sqrt((X_n * X_n + Y_n * Y_n) * (1 - e2_n * Math.Pow(Math.Sin(p0), 2))))));

            while (!(Math.Abs(p1 - p0) < epsilon))
            {

                p0 = p1; p1 = Math.Atan((Z_n / Math.Sqrt(X_n * X_n + Y_n * Y_n)) / (1 - (a_n * e2_n * Math.Cos(p0)) / (Math.Sqrt((X_n * X_n + Y_n * Y_n) * (1 - e2_n * Math.Pow(Math.Sin(p0), 2))))));

            }

            double phi_n = p1;
            double lambda_n = Math.Atan(Y_n / X_n);

            /**********************************************************************************************************************/
            /**        4) coordonnées géographiques NTF (phi_n,lambda_n)  coordonnées projetées en Lambert II étendu (X_l2e, Y_l2e) **/
            /**********************************************************************************************************************/

            // J'utilise les formules de projection et les constantes fournies par l'IGN dans un autre document :

            // avant tout on définit quelques constantes
            double n = 0.7289686274;
            double c = 11745793.39;
            double Xs = 600000.0;
            double Ys = 8199695.768;

            double e_n = Math.Sqrt(e2_n);
            double lambda0 = 0.04079234433198;   //correspond à la longitude en radian de Paris (2°20'14.025" E) par rapport à Greenwich
                                                 // puis on calcule la latitude isométrique
            double L = Math.Log(Math.Tan(Math.PI / 4 + phi_n / 2) * Math.Pow(((1 - e_n * Math.Sin(phi_n)) / (1 + e_n * Math.Sin(phi_n))), (e_n / 2)));

            // enfin on projette

            double X_l2e = Xs + c * Math.Exp((-n * L)) * Math.Sin(n * (lambda_n - lambda0));
            double Y_l2e = Ys - c * Math.Exp((-n * L)) * Math.Cos(n * (lambda_n - lambda0));

            double[] tabXY = new double[2];

            tabXY[0] = X_l2e;
            tabXY[1] = Y_l2e;

            return tabXY;
        }
        public static void insererElementDansLaTableElementComp(Point pt, string conString, int idElement, double[] tab, double minx93, double miny93)
        {
            string sqlQuery = string.Format("INSERT into COMP_ELEMENTS_COORDONNEES (COORDONNEE_X, COORDONNEE_Y,ELEMENT , MINX_LAMBERT2 , MINY_LAMBERT2 , MINX_LAMBERT93 , MINY_LAMBERT93 , ELEMENT_TYPE, TYPE_SPATIAL) values (@CoordonneX, @CoordonnneeY , @ElementID, @MinXLambert , @MinYLambert , @MinXLambert93 , @MinYLambert93 , @ElementType, @TypeSpatial)");
            SqlConnection con = new SqlConnection(conString);
            SqlCommand s = new SqlCommand(sqlQuery, con);
            s.Parameters.Add("@CoordonneX", SqlDbType.Float).Value = pt.x;
            s.Parameters.Add("@CoordonnneeY", SqlDbType.Float).Value = pt.y;
            s.Parameters.Add("@ElementID", SqlDbType.Int).Value = idElement;
            s.Parameters.Add("@MinXLambert", SqlDbType.Float).Value = tab[0];
            s.Parameters.Add("@MinYLambert", SqlDbType.Float).Value = tab[1];
            s.Parameters.Add("@MinXLambert93", SqlDbType.Float).Value = minx93;
            s.Parameters.Add("@MinYLambert93", SqlDbType.Float).Value = miny93;
            s.Parameters.Add("@ElementType", SqlDbType.VarChar).Value = "ELE";
            s.Parameters.Add("@TypeSpatial", SqlDbType.VarChar).Value = "POINT";
            con.Open();
            s.ExecuteNonQuery();
            con.Close();
        }
        public static Point convertToWGS84Deg(double x, double y, Zone zone)
        {

            Point pt = new Point(x, y, 0);
            pt = convertToWGS84(pt, zone);
            pt.toDegree();
            return pt;


        }
        public static Point convertToWGS84(Point org, Zone zone)
        {

            var lzone = new LambertZone(zone);

            if (zone == Zone.Lambert93)
            {
                return lambertToGeographic(org, lzone, LambertZone.LON_MERID_IERS, LambertZone.E_WGS84, LambertZone.DEFAULT_EPS);
            }
            else
            {
                Point pt1 = lambertToGeographic(org, lzone, LambertZone.LON_MERID_PARIS, LambertZone.E_CLARK_IGN, LambertZone.DEFAULT_EPS);

                Point pt2 = geographicToCartesian(pt1.x, pt1.y, pt1.z, LambertZone.A_CLARK_IGN, LambertZone.E_CLARK_IGN);

                pt2.translate(-168, -60, 320);

                //WGS84 refers to greenwich
                return cartesianToGeographic(pt2, LambertZone.LON_MERID_GREENWICH, LambertZone.A_WGS84, LambertZone.E_WGS84, LambertZone.DEFAULT_EPS);
            }
        }
        private static double lambertNormal(double lat, double a, double e)
        {

            return a / Math.Sqrt(1 - e * e * Math.Sin(lat) * Math.Sin(lat));
        }

        private static Point geographicToCartesian(double lon, double lat, double he, double a, double e)
        {
            double N = lambertNormal(lat, a, e);

            Point pt = new Point(0, 0, 0);

            pt.x = (N + he) * Math.Cos(lat) * Math.Cos(lon);
            pt.y = (N + he) * Math.Cos(lat) * Math.Sin(lon);
            pt.z = (N * (1 - e * e) + he) * Math.Sin(lat);

            return pt;
        }

        private static Point cartesianToGeographic(Point org, double meridien, double a, double e, double eps)
        {
            double x = org.x, y = org.y, z = org.z;

            double lon = meridien + Math.Atan(y / x);

            double module = Math.Sqrt(x * x + y * y);

            double phi0 = Math.Atan(z / (module * (1 - (a * e * e) / Math.Sqrt(x * x + y * y + z * z))));
            double phiI = Math.Atan(z / module / (1 - a * e * e * Math.Cos(phi0) / (module * Math.Sqrt(1 - e * e * Math.Sin(phi0) * Math.Sin(phi0)))));
            double delta = Math.Abs(phiI - phi0);
            while (delta > eps)
            {
                phi0 = phiI;
                phiI = Math.Atan(z / module / (1 - a * e * e * Math.Cos(phi0) / (module * Math.Sqrt(1 - e * e * Math.Sin(phi0) * Math.Sin(phi0)))));
                delta = Math.Abs(phiI - phi0);

            }

            double he = module / Math.Cos(phiI) - a / Math.Sqrt(1 - e * e * Math.Sin(phiI) * Math.Sin(phiI));

            Point pt = new Point(lon, phiI, he);

            return pt;
        }
        private static double latitudeFromLatitudeISO(double latISo, double e, double eps)
        {

            double phi0 = 2 * Math.Atan(Math.Exp(latISo)) - LambertZone.M_PI_2;
            double phiI = 2 * Math.Atan(Math.Pow((1 + e * Math.Sin(phi0)) / (1 - e * Math.Sin(phi0)), e / 2d) * Math.Exp(latISo)) - LambertZone.M_PI_2;
            double delta = Math.Abs(phiI - phi0);

            while (delta > eps)
            {
                phi0 = phiI;
                phiI = 2 * Math.Atan(Math.Pow((1 + e * Math.Sin(phi0)) / (1 - e * Math.Sin(phi0)), e / 2d) * Math.Exp(latISo)) - LambertZone.M_PI_2;
                delta = Math.Abs(phiI - phi0);
            }

            return phiI;
        }

        private static Point lambertToGeographic(Point org, LambertZone zone, double lonMeridian, double e, double eps)
        {
            double n = zone.n();
            double C = zone.c();
            double xs = zone.xs();
            double ys = zone.ys();

            double x = org.x;
            double y = org.y;


            double lon, gamma, R, latIso;

            R = Math.Sqrt((x - xs) * (x - xs) + (y - ys) * (y - ys));

            gamma = Math.Atan((x - xs) / (ys - y));

            lon = lonMeridian + gamma / n;

            latIso = -1 / n * Math.Log(Math.Abs(R / C));

            double lat = latitudeFromLatitudeISO(latIso, e, eps);

            Point dest = new Point(lon, lat, 0);
            return dest;
        }
        public static Point convertToWGS84(double x, double y, Zone zone)
        {

            Point pt = new Point(x, y, 0);
            return convertToWGS84(pt, zone);
        }

        #region ScriptResults declaration
        /// <summary>
        /// This enum provides a convenient shorthand within the scope of this class for setting the
        /// result of the script.
        /// 
        /// This code was generated automatically.
        /// </summary>
        enum ScriptResults
        {
            Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
            Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
        };
        #endregion

    }
    public enum Zone
    {
        LambertI = 0, LambertII = 1, LambertIII = 2, LambertIV = 3, LambertIIExtended = 4, Lambert93 = 5
    }
    public enum Unit { Degree, Grad, Radian, Meter };
    public class Point
    {
        private const double radianTodegree = 180.0 / Math.PI;

        public Point(double x, double y, double z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public double x { get; set; }
        public double y { get; set; }
        public double z { get; set; }


        public void translate(double x, double y, double z)
        {

            this.x += x;
            this.y += y;
            this.z += z;
        }
        private void Scale(double scale)
        {
            this.x *= scale;
            this.y *= scale;
            this.z *= scale;
        }

        public void toDegree()
        {
            Scale(radianTodegree);
        }
    }

    public class LambertZone
    {

        private readonly static double[] LAMBERT_N = { 0.7604059656, 0.7289686274, 0.6959127966, 0.6712679322, 0.7289686274, 0.7256077650 };
        private readonly static double[] LAMBERT_C = { 11603796.98, 11745793.39, 11947992.52, 12136281.99, 11745793.39, 11754255.426 };
        private readonly static double[] LAMBERT_XS = { 600000.0, 600000.0, 600000.0, 234.358, 600000.0, 700000.0 };
        private readonly static double[] LAMBERT_YS = { 5657616.674, 6199695.768, 6791905.085, 7239161.542, 8199695.768, 12655612.050 };

        public readonly static double M_PI_2 = Math.PI / 2.0;
        public readonly static double DEFAULT_EPS = 1e-10;
        public readonly static double E_CLARK_IGN = 0.08248325676;
        public readonly static double E_WGS84 = 0.08181919106;

        public readonly static double A_CLARK_IGN = 6378249.2;
        public readonly static double A_WGS84 = 6378137.0;
        public readonly static double LON_MERID_PARIS = 0;
        public readonly static double LON_MERID_GREENWICH = 0.04079234433;
        public readonly static double LON_MERID_IERS = 3.0 * Math.PI / 180.0;

        public LambertZone(Zone zone)
        {
            this.lambertZone = zone;
        }

        public double n()
        {
            return LAMBERT_N[(int)lambertZone];
        }

        public double c()
        {
            return LAMBERT_C[(int)lambertZone];
        }
        public double xs()
        {
            return LAMBERT_XS[(int)lambertZone];
        }
        public double ys()
        {
            return LAMBERT_YS[(int)lambertZone];
        }

        public Zone lambertZone { get; private set; }

    }
}

I resolved the issue in another way as the Azure database keeps cutting the connexion and can't modify the azure security settings. I modified the script and now I have a job that runs ones a week to insert only the new data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM