CSharp:Esempi LinQ fusione datatable
From Aino Wiki
Esempio completo funzionante:
public static DataTable Step5_MergeDataTable(string fileNameValue, Dictionary<string, InfoMappingAndRules> dictInfoMapping4File, DataSet dsSourceFiles, List<SynchronizationsDownloads> lsd, ref List<SynchronizationsMapping> lsm, ref string strMsgError) { DataTable dtFull = new DataTable(); strMsgError = string.Empty; string[] arrFileToImport = fileNameValue.Split(','); string strCSVAllPositionToRemove = string.Empty; int nrFieldsOk = 0; int positionToRemove = -1; int i = 0; string synchronizationID = lsd.Count > 0 ? lsd[0].SynchronizationID : string.Empty; #region CREAZIONE elenco di tutti i mapping per TUTTI Files\DataTable --> tabella finale //Si crea un lsm con tutti i mapping per la Synchro quindi adatti ad un unico DataTable complessivo //ciò escludendo i campi di mapping DOPPIONI foreach (SynchronizationsDownloads sd in lsd) { List<SynchronizationsMapping> lsmX = new List<SynchronizationsMapping>(); if (dictInfoMapping4File.ContainsKey(sd.DestinationFileName)) { lsmX = dictInfoMapping4File[sd.DestinationFileName].LstSyncMappings; foreach (SynchronizationsMapping sm in lsmX) { if (!SynchronizationsMapping.SourceColumnAlreadyAdded(lsm, sm) && !sm.DestinationColumnName.Contains(SynchronizationsMapping.RootNameDestField4FilterRules)) { lsm.Add(sm); } //else //{ i++; //PER DEBUG !!!! conta gli scartati //} } } } #endregion #region Costruzione Info x trasformazione in funzine del Tipo colonna tabella Import //Dictionary<string, string> dictColDestType = new Dictionary<string, string>(); //Contiene i tipi dei campi della Tabella IMPORT //string secondKeyFieldName = string.Empty; //Dictionary<string, string> dictColMapping = BuildDictColMapping(lsm, ref secondKeyFieldName, ref dictColDestType); #endregion if (arrFileToImport.Length > 1) { #region CASO PIU' DI un File\DataTable dtFull = dsSourceFiles.Tables[arrFileToImport[0]].Clone(); //<-- Di Default E PER IPOTESI, il primo file è quello più importante con info pilota nrFieldsOk = dsSourceFiles.Tables[arrFileToImport[0]].Columns.Count; //Nome campo corrispondente al ProductCode della tabella di Import string sourceKeyFieldName0 = string.Empty; string sourceKeyFieldName1 = string.Empty; sourceKeyFieldName0 = SynchronizationsMapping.GetSourceColumnIndexKeyByDestinationFileName(lsd, dictInfoMapping4File[arrFileToImport[0]].LstSyncMappings, arrFileToImport[0]); sourceKeyFieldName1 = SynchronizationsMapping.GetSourceColumnIndexKeyByDestinationFileName(lsd, dictInfoMapping4File[arrFileToImport[1]].LstSyncMappings, arrFileToImport[1]); string destinationKeyFieldName = SynchronizationsMapping.GetKeyFieldNames(lsm); //E' unico ed è: ProductCode #region CREAZIONE MATRICE dei valori da riporre nel nuovo DT omnicomprensivo object[] emptyObj = new object[dsSourceFiles.Tables[arrFileToImport[1]].Columns.Count]; //if (synchronizationID == "ESPSYN") //{ // emptyObj = new string[] { "xxx", "0", "0" }; //emptyObj = new string[] { "xxx", "-9999", "-9999" }; //} //Prima MATRICE DI VALORI per la prima COPPIA di Files\Datatable da integrare per ogni file successivo al SECONDO var rowData = from row1 in dsSourceFiles.Tables[arrFileToImport[0]].AsEnumerable() join row2 in dsSourceFiles.Tables[arrFileToImport[1]].AsEnumerable() on row1.Field<string>(sourceKeyFieldName0).Trim() equals row2.Field<string>(sourceKeyFieldName1).Trim() into row1X from rowY in row1X.DefaultIfEmpty() select row1.ItemArray.Concat(rowY == null ? emptyObj : rowY.ItemArray).ToArray(); //row1.ItemArray.Concat(rowY == null ? new object[0] : rowY.ItemArray).ToArray(); //CICLO x ogni altro file se c'è, successivo al primo //per eliminare i valori di informazioni RIPETUTE una su tutte è il campo chiave che deve essere in ciascun file/DataTable!!! //Preliminare, segno tutti i campi del primo file foreach (DataColumn dc in dtFull.Columns) { SynchronizationsMapping.GetDestinationColumNameAndMark(lsm, dc.ColumnName); } string destinationColumName = string.Empty; //dal secondo file e relativo gruppo di colonne for (int f = 1; f < arrFileToImport.Length; f++) { string sourceKeyFieldNameF = string.Empty; i = 0; positionToRemove = -1; //Costruisce l'insieme delle colonne di 2 File ovvero DataTable var dt2Columns = dsSourceFiles.Tables[arrFileToImport[f]].Columns.OfType<DataColumn>() .Select(dc => new DataColumn(dc.ColumnName, dc.DataType, dc.Expression, dc.ColumnMapping)); //Aggiunge al DataTable PRINCIPALE 'dtFull' le colonne degli altri files foreach (DataColumn dc in dt2Columns) { if (!dtFull.Columns.Contains(dc.ColumnName)) { destinationColumName = SynchronizationsMapping.GetDestinationColumNameAndMark(lsm, dc.ColumnName); if (destinationColumName == destinationKeyFieldName) //non si aggiunge la colonna se il Destination Field è Chiave { positionToRemove = i; } else { dtFull.Columns.Add(dc); } } else { destinationColumName = SynchronizationsMapping.GetDestinationColumNameAndMark(lsm, dc.ColumnName); if (destinationColumName == destinationKeyFieldName) positionToRemove = i; // è UNO solo, per ipotesi !!! ed è relativo al file\DataTable corrente else { string newSourceColumnIndex = dc.ColumnName + "#" + destinationColumName; //ridenominare anche il source del mapping dc.ColumnName = SynchronizationsMapping.RenameSourceColumnIndex(lsm, dc.ColumnName, destinationColumName, newSourceColumnIndex); dtFull.Columns.Add(dc); } } i++; } //Aggiustamento posizione if (positionToRemove > -1) { positionToRemove += nrFieldsOk + positionToRemove; nrFieldsOk += i; strCSVAllPositionToRemove += (string.IsNullOrEmpty(strCSVAllPositionToRemove) ? "," : string.Empty) + positionToRemove + ","; } //Integrazione della MATRICE DI VALORI, per le coppie di DataTable successive alla prima quindi dalla coppia 3-4 DataTable if (f > 1) { int nrColSecondFile = dsSourceFiles.Tables[arrFileToImport[f]].Columns.Count; //ATTENZIONE NON CANCELLARE O SPOSTARE => Baco di Linq, non calcolerebbe correttamente il nr di colonne sourceKeyFieldNameF = SynchronizationsMapping.GetSourceColumnIndexKeyByDestinationFileName(lsd, dictInfoMapping4File[arrFileToImport[f]].LstSyncMappings, arrFileToImport[f]); rowData = from row1 in rowData join row2 in dsSourceFiles.Tables[arrFileToImport[f]].AsEnumerable() on row1[0] equals row2.Field<string>(sourceKeyFieldNameF).Trim() into row1X from rowY in row1X.DefaultIfEmpty() select row1.Concat(rowY == null ? new object[nrColSecondFile] : rowY.ItemArray).ToArray(); } } //Fine file\DataTable corrente #endregion //Riempimento DataTable con i Valori dai 2\n DataTable. rowData ha TUTTI i valori !!! int rowInserted = 0; int j = 0; try { if (!string.IsNullOrEmpty(strCSVAllPositionToRemove)) { foreach (object[] values in rowData) //Riga definitiva con TUTTI i valori da porre nel DataTable DESTINAZIONE { j = 0; DataRow dr = dtFull.NewRow(); for (int c = 0; c < values.Length; c++) { if (strCSVAllPositionToRemove.IndexOf("," + c + ",") < 0) { //string destinationColumnName = dictColMapping[ dr.Table.Columns[j].ColumnName]; //dr[j] = TransformFieldValueByDestType(singleValue, destinationColumnName, dictColDestType, true); //string singleValue = values[c].ToString(); dr[j] = values[c]; j++; } } dtFull.Rows.Add(dr); rowInserted++; } } else { #region Caso IMPROBABILE, nessun campo chiave di collegamento foreach (object[] values in rowData) { DataRow dr = dtFull.NewRow(); for (int c = 0; c <= dtFull.Columns.Count; c++) { dr[c] = values[c]; } dtFull.Rows.Add(dr); } #endregion } } catch (Exception ex) { string lastProdCode = string.Empty; strMsgError = string.Format("Errore: {0}.\r\nRighi inseriti: '{1}', j='{2}'", ex.Message, rowInserted, j); try { lastProdCode = dtFull.Rows[rowInserted-1][sourceKeyFieldName0].ToString(); } catch {} strMsgError = string.Format("{0}, ultimo productCode '{1}'", strMsgError, lastProdCode); //Serve a poco perchè l'ordinamento di inserimento è diverso...... } #endregion } else //Caso un solo file da porre in DataTable: { dtFull = dsSourceFiles.Tables[arrFileToImport[0]]; } //Verifica finale if (dtFull.Rows.Count == 0) { strMsgError = "Nessuna informazione nel DataTable completo da importare sl DB."; } return dtFull; }
C# | LinQ | Esempi LinQ