示例#1
0
        public bool ControlloStrutturaDB(out bool esito, out List <string> listaErr)
        {
            esito    = false;
            listaErr = new List <string>();

            //*****Popolo strutturaInDef
            List <AnalisiTabella> strutturaInDef = new List <AnalisiTabella>();
            AnalisiTabella        analisiTabDef; AnalisiColonna analisiColDef; AnalisiFK analisiFK; Type tipoDB, tipoTabella;

            analisiTabDef = null;

            tipoDB = this.GetType(); //Prendo il tipo della classe che eredita da DB

            foreach (PropertyInfo proprietàTab in tipoDB.GetProperties())
            { //Scorro tutti i field della classe che eredita da DB alla ricerca delle tabelle
                if (proprietàTab.PropertyType.IsSubclassOf(typeof(TabellaBase)))
                {
                    //If proprietàTab.FieldType.BaseType = GetType(TabellaBase) Then

                    TabellaBase tab = (TabellaBase)proprietàTab.GetValue(this);
                    analisiTabDef = new AnalisiTabella(tab);
                    tipoTabella   = tab.GetType();

                    foreach (ForeignKey FK in tab.listaFK)
                    {
                        analisiFK = new AnalisiFK(FK); //Per controllare i FK non posso usare la lista interna a tab poichè non mi posso segnare se è stato controllato
                        analisiTabDef.foreignKeys.Add(analisiFK);
                    }

                    foreach (FieldInfo proprietaCampo in tipoTabella.GetFields())
                    {
                        if (proprietaCampo.FieldType == typeof(Column))
                        {
                            Column col = (Column)proprietaCampo.GetValue(tab);
                            if (col == null)
                            {
                                listaErr.Add("In definizione nella tab:<" + tab.Nm + "> è definita la colonna " + proprietaCampo.Name + " ma il valore è null, manca quindi l'instanza della colonna nel costruttore della tabella");
                                continue;
                            }
                            analisiColDef = new AnalisiColonna(col);
                            analisiTabDef.colonne.Add(analisiColDef);
                        }
                    }
                    strutturaInDef.Add(analisiTabDef);
                }
            }


            //*****Leggo le informazioni che mi servono da DB per poter fare il confronto
            SqlObj    sql = new SqlObj();
            DataTable sqlTab = new DataTable();
            DataTable sqlCampi = new DataTable();
            DataTable sqlKeysPrim = new DataTable();
            DataTable sqlIdent = new DataTable();
            DataTable sqlFK = new DataTable();
            string    nomeTabInSql, nomeColInSql, testoErrTab, testoErrCol;

            ColumnTypes.Base tipoColInSql;


            if (sql.ExecQuery(Sql.sel + "table_name FROM information_schema.tables", res: ref sqlTab) == false)
            {
                return(false);                                                                                                //Recupera sia tabelle che viste
            }
            if (sql.ExecQuery(Sql.sel + "* FROM information_schema.columns", res: ref sqlCampi) == false)
            {
                return(false);
            }

            if (sql.ExecQuery(Sql.sel + "ku.table_name AS tab, ku.column_name AS col " +
                              "FROM information_schema.table_constraints AS tc " +
                              "INNER JOIN information_schema.key_column_usage AS ku ON tc.constraint_type = 'PRIMARY KEY' AND tc.constraint_name = ku.constraint_name", res: ref sqlKeysPrim) == false)
            {
                return(false);
            }

            if (sql.ExecQuery(Sql.sel + "obj.name AS tab, ident.name AS col FROM sys.identity_columns AS ident " +
                              "INNER JOIN sys.objects as obj ON obj.object_id = ident.object_id " +
                              "where obj.type_desc != 'INTERNAL_TABLE'", res: ref sqlIdent) == false)
            {
                return(false);
            }

            if (sql.ExecQuery(Sql.sel + "obj.name AS nome, tab1.name AS tab, col1.name AS col, tab2.name AS tabFk, col2.name AS colFk " +
                              "FROM sys.foreign_key_columns fkc " +
                              "INNER JOIN sys.objects obj ON obj.object_id = fkc.constraint_object_id " +
                              "INNER JOIN sys.tables tab1 ON tab1.object_id = fkc.parent_object_id " +
                              "INNER JOIN sys.columns col1 ON col1.column_id = parent_column_id And col1.object_id = tab1.object_id " +
                              "INNER JOIN sys.tables tab2 ON tab2.object_id = fkc.referenced_object_id " +
                              "INNER JOIN sys.columns col2 ON col2.column_id = fkc.referenced_column_id AND col2.object_id = tab2.object_id ", res: ref sqlFK) == false)
            {
                return(false);
            }


            foreach (DataRow tabInSql in sqlTab.Rows)
            {
                nomeTabInSql = (string)tabInSql["TABLE_NAME"];

                //*****verifica esistenza tabella in definizione
                var listaTabInDef = from tmp in strutturaInDef where tmp.tabella.Nm == nomeTabInSql select tmp;

                if (listaTabInDef.Count() == 0)
                {
                    listaErr.Add("In sql è presente la tabella:<" + nomeTabInSql + "> non presente in definizione");
                    continue;
                }
                else if (listaTabInDef.Count() > 1)
                {
                    listaErr.Add("In definizione c'è più di una tabella con il nome:<" + nomeTabInSql + ">");
                    continue;
                }
                else
                {
                    analisiTabDef = listaTabInDef.ElementAt(0);
                }

                testoErrTab = "per la tabella:<" + nomeTabInSql + ">";


                foreach (DataRow colInSql in sqlCampi.Select("TABLE_NAME='" + nomeTabInSql + "'"))
                {
                    nomeColInSql = (string)colInSql["COLUMN_NAME"];
                    testoErrCol  = " la colonna:<" + nomeColInSql + ">";

                    //*****verifica esistenza colonne in definizione

                    var    listaColInDef = from tmp in analisiTabDef.colonne where tmp.colonna.Nm == nomeColInSql select tmp;
                    Column colInDef;

                    if (listaColInDef.Count() == 0)
                    {
                        listaErr.Add("In sql " + testoErrTab + " è presente" + testoErrCol + ", non presente in definizione");
                        continue;
                    }
                    else if (listaTabInDef.Count() > 1)
                    {
                        listaErr.Add("In definizione " + testoErrTab + " c'è più di una colonna con il nome:<" + nomeColInSql + ">");
                        continue;
                    }
                    else
                    {
                        colInDef = listaColInDef.ElementAt(0).colonna;
                    }


                    switch (colInSql["IS_NULLABLE"])
                    {
                    case "NO":
                        if (colInDef.ValNull == true)
                        {
                            listaErr.Add("In sql " + testoErrTab + testoErrCol + " non può essere null, in definizione si");                               //Non serve Continue For cos' controllo anche altri errori
                        }
                        break;

                    case "YES":
                        if (colInDef.ValNull == false)
                        {
                            listaErr.Add("In sql " + testoErrTab + testoErrCol + " può essere null, in definizione no");                                //Non serve Continue For cos' controllo anche altri errori
                        }
                        break;

                    default:
                        Log.main.Add(new Mess(LogType.ERR, Log.main.errUserText, "In sql " + testoErrTab + testoErrCol + " ha il valore IS_NULLABLE sconosciuto, valore:<" + colInSql["IS_NULLABLE"].ToString() + ">"));
                        continue;
                    }


                    if (Convert.IsDBNull(colInSql["COLUMN_DEFAULT"]))
                    {
                        if (colInDef.ValPred != null)
                        {
                            listaErr.Add("In sql " + testoErrTab + testoErrCol + " non ha valore predefinito, in definizione si, colInDef.valPred:<" + colInDef.ValPred + ">");                           //Non serve Continue For cos' controllo anche altri errori
                        }
                    }
                    else
                    {
                        if (colInDef.ValPred == null)
                        {
                            listaErr.Add("In sql " + testoErrTab + testoErrCol + " ha valore predefinito, in definizione no, COLUMN_DEFAULT:<" + colInSql["COLUMN_DEFAULT"].ToString() + ">");                           //Non serve Continue For cos' controllo anche altri errori
                        }
                        if (Regex.IsMatch((string)colInSql["COLUMN_DEFAULT"], @"^((\(\(){1}[0-9]+(\)\)){1}|(\('){1}[\s\S]*('\)){1})$"))
                        { //Regex: ((num)) or ('str') , str può essere 0 caratteri num no
                            string valPredInSql = ((string)colInSql["COLUMN_DEFAULT"]).Right(-2).Left(-2);
                            if (valPredInSql != (string)colInDef.ValPred)
                            {
                                listaErr.Add("In sql " + testoErrTab + testoErrCol + " ha valore predefinito:<" + valPredInSql + ">, in definizione:<" + colInDef.ValPred + ">");                                           //Non serve Continue For cos' controllo anche altri errori
                            }
                        }
                        else
                        {
                            Log.main.Add(new Mess(LogType.ERR, Log.main.errUserText, "In sql " + testoErrTab + testoErrCol + " ha il valore COLUMN_DEFAULT con formato sconosciuto, valore:<" + colInSql["COLUMN_DEFAULT"].ToString() + ">"));
                            continue;
                        }
                    }

                    if (sqlKeysPrim.Select("tab='" + nomeTabInSql + "' AND col='" + nomeColInSql + "'").Count() == 1)
                    {
                        if (colInDef.PrimKey == false)
                        {
                            listaErr.Add("In sql " + testoErrTab + testoErrCol + " è chiave primaria, in definizione no");                            //Non serve Continue For cos' controllo anche altri errori
                        }
                    }
                    else
                    {
                        if (colInDef.PrimKey == true)
                        {
                            listaErr.Add("In sql " + testoErrTab + testoErrCol + " non è chiave primaria, in definizione si");                           //Non serve Continue For cos' controllo anche altri errori
                        }
                    }


                    //*****verifica del tipo di colonna
                    switch (colInSql["DATA_TYPE"].ToString().ToLower())
                    { //I tipi che hanno un costruttore devono essere trattati singolarmente
                    case "nvarchar":
                        if (Convert.IsDBNull(colInSql["CHARACTER_MAXIMUM_LENGTH"]))
                        {       //se è NVarChar(MAX) la colonna CHARACTER_MAXIMUM_LENGTH vale -1
                            Log.main.Add(new Mess(LogType.ERR, Log.main.errUserText, "In sql " + testoErrTab + testoErrCol + " è di tipo NVarChar ma il valore di CHARACTER_MAXIMUM_LENGTH è null"));
                            continue;
                        }
                        else if (colInSql["CHARACTER_MAXIMUM_LENGTH"].IsNumeric() == false)
                        {
                            Log.main.Add(new Mess(LogType.ERR, Log.main.errUserText, "In sql " + testoErrTab + testoErrCol + " è di tipo NVarChar ma il valore di CHARACTER_MAXIMUM_LENGTH non è numerico, valore:<" + colInSql["CHARACTER_MAXIMUM_LENGTH"].ToString() + ">"));
                            continue;
                        }
                        else if (Num.ContieneCaratNum(colInSql["CHARACTER_MAXIMUM_LENGTH"].ToString(), ctrlSegno: false))
                        {
                            Log.main.Add(new Mess(LogType.ERR, Log.main.errUserText, "In sql " + testoErrTab + testoErrCol + " è di tipo NVarChar ma il valore di CHARACTER_MAXIMUM_LENGTH contiene caratteri disattesi, valore:<" + colInSql["CHARACTER_MAXIMUM_LENGTH"].ToString() + ">"));
                            continue;
                        }
                        else if (colInSql["CHARACTER_MAXIMUM_LENGTH"].ToString() == "-1")
                        {     //-1 è NVarChar(MAX)
                            tipoColInSql = new ColumnTypes.NVarChar("MAX");
                        }
                        else
                        {
                            tipoColInSql = new ColumnTypes.NVarChar(colInSql["CHARACTER_MAXIMUM_LENGTH"].ToString());
                        }
                        break;

                    case "decimal":

                        if (Convert.IsDBNull(colInSql["NUMERIC_PRECISION"]) || Convert.IsDBNull(colInSql["NUMERIC_SCALE"]))
                        {
                            Log.main.Add(new Mess(LogType.ERR, Log.main.errUserText, "In sql " + testoErrTab + testoErrCol + " è di tipo Decimal ma il valore di NUMERIC_PRECISION o NUMERIC_SCALE è null, NUMERIC_PRECISION:<" + colInSql["NUMERIC_PRECISION"].ToString() + ">, NUMERIC_SCALE:<" + colInSql["NUMERIC_SCALE"].ToString() + ">"));
                            continue;
                        }
                        else if (colInSql["NUMERIC_PRECISION"].IsNumeric() == false || colInSql["NUMERIC_SCALE"].IsNumeric() == false)
                        {
                            Log.main.Add(new Mess(LogType.ERR, Log.main.errUserText, "In sql " + testoErrTab + testoErrCol + " è di tipo Decimal ma il valore di NUMERIC_PRECISION o NUMERIC_SCALE non è numerico, NUMERIC_PRECISION:<" + colInSql["NUMERIC_PRECISION"].ToString() + ">, NUMERIC_SCALE:<" + colInSql["NUMERIC_SCALE"].ToString() + ">"));
                            continue;
                        }
                        else if (Num.ContieneCaratNum(colInSql["NUMERIC_PRECISION"].ToString()) || Num.ContieneCaratNum(colInSql["NUMERIC_SCALE"].ToString()))
                        {
                            Log.main.Add(new Mess(LogType.ERR, Log.main.errUserText, "In sql " + testoErrTab + testoErrCol + " è di tipo Decimal ma il valore di NUMERIC_PRECISION o NUMERIC_SCALE contiene caratteri disattesi, NUMERIC_PRECISION:<" + colInSql["NUMERIC_PRECISION"].ToString() + ">, NUMERIC_SCALE:<" + colInSql["NUMERIC_SCALE"].ToString() + ">"));
                            continue;
                        }
                        else
                        {
                            tipoColInSql = new ColumnTypes.Decimal(Convert.ToUInt32(colInSql["NUMERIC_PRECISION"]), Convert.ToUInt32(colInSql["NUMERIC_SCALE"]));
                        }
                        break;

                    default:      //Tipo di colonna senza costruttore
                        var tipo = from tmp in Assembly.GetExecutingAssembly().GetTypes()
                                   where tmp.IsClass == true && tmp.BaseType == typeof(ColumnTypes.Base) && tmp.Name.ToLower() == (string)colInSql["DATA_TYPE"].ToString().ToLower()
                                   select tmp;

                        if (tipo.Count() == 0)
                        {
                            listaErr.Add("In sql " + testoErrTab + testoErrCol + " è di tipo sconoscito, DATA_TYPE:<" + colInSql["DATA_TYPE"].ToString() + ">");
                            continue;
                        }
                        tipoColInSql = (ColumnTypes.Base)Activator.CreateInstance(tipo.ElementAt(0));
                        break;
                    }

                    if (tipoColInSql.GetType() != colInDef.Tipo.GetType())
                    {
                        listaErr.Add("In sql " + testoErrTab + testoErrCol + " ha il tipo è diverso alla definizione, tipoColInSql:<" + tipoColInSql.GetType().Name + ">, colInDef:<" + colInDef.Tipo.GetType().Name + ">");
                    }
                    else
                    {  //Se sono dello stesso tipo controllo il contenuto (le variabili interne)
                        string serialColInSql, serialColInDef;
                        serialColInSql = serialColInDef = "";
                        if (Serialize.SerializeInText(tipoColInSql, ref serialColInSql) == false || Serialize.SerializeInText(colInDef.Tipo, ref serialColInDef) == false)
                        {
                            continue;
                        }

                        if (serialColInSql.ToLower() != serialColInDef.ToLower())
                        {
                            listaErr.Add("In sql " + testoErrTab + testoErrCol + " ha il contenuto è diverso dalla definizione" + Util.crLf + Util.crLf +
                                         "serialColInSql:<" + serialColInSql + ">" + Util.crLf + Util.crLf +
                                         "serialColInDef:<" + serialColInDef + ">");
                        }
                    }
                    listaColInDef.ElementAt(0).controllato = true;
                }


                //*****Verifica del campo Identity della tabella
                DataRow[] colIdentInSql = sqlIdent.Select("tab='" + nomeTabInSql + "'");
                string    colIdentInDef = analisiTabDef.tabella.NomeColIdentity;

                if (colIdentInSql.Count() == 1)
                {
                    if (colIdentInSql[0]["col"].ToString() != colIdentInDef)
                    {
                        listaErr.Add("In sql " + testoErrTab + " la colonna identity è diversa da quella in definizione, colInSql:<" + colIdentInSql[0]["col"].ToString() + ">, colInDef:<" + colIdentInDef + ">");
                    }
                }
                else
                {
                    if (colIdentInDef != "")
                    {
                        listaErr.Add("In sql " + testoErrTab + " non c'è la colonna identity, in definizione si, nome colonna:<" + colIdentInDef + ">");
                    }
                }


                //*****Verifica delle foreign key

                foreach (DataRow fkInSql in sqlFK.Select("tab='" + nomeTabInSql + "'"))
                {
                    var        listaFkInDef = from tmp in analisiTabDef.foreignKeys where tmp.foreignKey.nome == fkInSql["nome"].ToString() select tmp;
                    ForeignKey fkInDef; string testoErrFk;

                    testoErrFk = " la foreign key:<" + fkInSql["nome"] + ">";

                    if (listaFkInDef.Count() == 0)
                    {
                        listaErr.Add("In sql " + testoErrTab + " c'è" + testoErrFk + ", in definizione no");
                        continue;
                    }

                    fkInDef = listaFkInDef.ElementAt(0).foreignKey;

                    if (fkInDef.tab != fkInSql["tab"].ToString())
                    {
                        listaErr.Add("In sql " + testoErrTab + testoErrFk + " ha come tabella:<" + fkInSql["tab"] + "> mentre in definizione è:<" + fkInDef.tab + ">");
                    }

                    if (fkInDef.col != fkInSql["col"].ToString())
                    {
                        listaErr.Add("In sql " + testoErrTab + testoErrFk + " ha come colonna:<" + fkInSql["col"] + "> mentre in definizione è:<" + fkInDef.col + ">");
                    }

                    if (fkInDef.tabFk != fkInSql["tabFk"].ToString())
                    {
                        listaErr.Add("In sql " + testoErrTab + testoErrFk + " ha come tabellaFk:<" + fkInSql["tabFk"] + "> mentre in definizione è:<" + fkInDef.tabFk + ">");
                    }

                    if (fkInDef.colFk != fkInSql["colFk"].ToString())
                    {
                        listaErr.Add("In sql " + testoErrTab + testoErrFk + " ha come colonnaFk:<" + fkInSql["colFk"] + "> mentre in definizione è:<" + fkInDef.colFk + ">");
                    }

                    listaFkInDef.ElementAt(0).controllato = true;
                }

                analisiTabDef.controllato = true;
            }

            //*****Ricerca dei non controllati (Significa presenti in definizione ma non presenti in sql)
            foreach (AnalisiTabella analisiTabInDef in strutturaInDef)
            {
                if (analisiTabInDef.controllato == false)
                {
                    listaErr.Add("In sql la tabella:<" + analisiTabInDef.tabella.Nm + "> non esiste");
                    continue;
                }

                foreach (AnalisiColonna analisiColInDef in analisiTabInDef.colonne)
                {
                    if (analisiColInDef.controllato == false)
                    {
                        listaErr.Add("In sql nella tabella:<" + analisiTabInDef.tabella.Nm + "> la colonna:<" + analisiColInDef.colonna.Nm + "> non esiste");
                    }
                }

                foreach (AnalisiFK analisiFKInDef in analisiTabInDef.foreignKeys)
                {
                    if (analisiFKInDef.controllato == false)
                    {
                        listaErr.Add("In sql nella tabella:<" + analisiTabInDef.tabella.Nm + "> il foreign key:<" + analisiFKInDef.foreignKey.nome + "> non esiste");
                    }
                }
            }
            if (listaErr.Count() == 0)
            {
                esito = true;
            }

            return(true);
        }