///////////////////////////////////////////////////////////////////////////////////////////////// private void ReadDependanceParente( string strPropriete, CListeObjetsDonnees lstSource, CListeObjetsDonnees.CArbreProps arbre, CInfoRelation relation) { int nNbTotal = lstSource.Count; string strKey = relation.RelationKey; Type tp = null; PropertyInfo info = lstSource.TypeObjets.GetProperty(strPropriete); if (info == null) { return; } tp = info.PropertyType; if (tp != null && typeof(CObjetDonneeAIdNumerique).IsAssignableFrom(tp)) { //Crée les paquets ArrayList lstPaquets = new ArrayList(); Hashtable tableIdsParentTraites = new Hashtable(); int nPaquet = 0; string strChampFille = relation.ChampsFille[0]; string strPaquetEnCours = ""; int nNbInPaquet = 0; for (int n = 0; n < lstSource.View.Count; n++) { DataRow row = lstSource.View.GetRow(n); string strCle = row[strChampFille].ToString(); if (strCle != "") { if (tableIdsParentTraites[strCle] == null) { tableIdsParentTraites[strCle] = true; strPaquetEnCours += strCle + ","; nNbInPaquet++; if (nNbInPaquet >= CListeObjetsDonnees.c_nNbLectureParLotFils) { strPaquetEnCours = "(" + strPaquetEnCours.Substring(0, strPaquetEnCours.Length - 1) + ")"; lstPaquets.Add(strPaquetEnCours); strPaquetEnCours = ""; nNbInPaquet = 0; } } } } if (strPaquetEnCours.Length > 0) { strPaquetEnCours = "(" + strPaquetEnCours.Substring(0, strPaquetEnCours.Length - 1) + ")"; lstPaquets.Add(strPaquetEnCours); } //Lit les relations par paquet int nNbPaquets = lstPaquets.Count; for (nPaquet = 0; nPaquet < nNbPaquets; nPaquet++) { string strPaquet = (string)lstPaquets[nPaquet]; if (strPaquet != "()") { CListeObjetsDonnees listeParent = new CListeObjetsDonnees(lstSource.ContexteDonnee, tp); listeParent.ModeSansTri = true; listeParent.PreserveChanges = true; listeParent.Filtre = new CFiltreData(relation.ChampsParent[0] + " in " + strPaquet); listeParent.AssureLectureFaite(); //Indique que les lignes ont été lues //Stef 2/12/2011 : non, on n'indique pas que c'est lu puisqu'il //s'agit de dépendances parentes ! //Ca pose le problème suivant : si on est sur une table hiérarchique, //lorsqu'on lit le parent (d'un projet par exemple), le fait de //dire que les dépendances sont lues implique qu'on indique //qu'on a lu les fils. //De ma compréhension à ce jour, on ne gère pas de colonne //indiquant si la dépendance a été chargé pour des dépendances //parentes /*if ( lstSource.View.Table.Columns[strKey] != null ) * { * for ( int nRow = 0; nRow < lstSource.View.Count; nRow++ ) * { * CContexteDonnee.ChangeRowSansDetectionModification ( lstSource.View.GetRow ( nRow ), strKey, true ); * } * }*/ listeParent.ReadDependances(arbre); } } } }
///////////////////////////////////////////////////////////// private void AddFields(Type leType, Hashtable tableIdsDefinisDansTableAttribute, Hashtable tableIds, bool bRelationsOnly) { if (leType == null) { return; } if (!bRelationsOnly) { //Relation vers la table Versions #region Relation vers la table versions if (!typeof(IObjetSansVersion).IsAssignableFrom(leType)) { CInfoChampTable champVersion = new CInfoChampTable(CSc2iDataConst.c_champIdVersion, typeof(int), 0, false, false, true, false, true); //Stef 06 10 2009 : le champ version n'est plus indexé seul, il est indexé //avec le champ deleted champVersion.IsIndex = true; champVersion.Propriete = "IdVersionDatabase"; m_listeChamps.Add(champVersion); m_tableChamps[champVersion.NomChamp] = champVersion; //Stef 29/08/2008 : suppression du lien à la version, trop lent ! /*CInfoRelation relationVersion = new CInfoRelation( * CVersionDonnees.c_nomTable, * NomTable, * new string[] { CVersionDonnees.c_champId }, * new string[] { champVersion.NomChamp }, * false, * true, * true, * false); * relationVersion.NomConvivial = "Version"; * m_listeRelationsParentes.Add(relationVersion);*/ CInfoChampTable champIdOriginal = new CInfoChampTable(CSc2iDataConst.c_champOriginalId, typeof(int), 0, false, false, true, false, true); champIdOriginal.IsIndex = true; m_listeChamps.Add(champIdOriginal); CInfoChampTable champIsDeleted = new CInfoChampTable(CSc2iDataConst.c_champIsDeleted, typeof(bool), 0, false, false, false, false, true); champIsDeleted.Propriete = "IsDeleted"; m_listeChamps.Add(champIsDeleted); //Stef 06 10 2009 : le champ version n'est plus indexé seul, il est indexé //avec le champ deleted /*CInfoIndexTable infoIndex = new CInfoIndexTable( * CSc2iDataConst.c_champIdVersion, CSc2iDataConst.c_champIsDeleted); * m_listeIndexsSupplementaires.Add(infoIndex);*/ } } #endregion foreach (PropertyInfo property in leType.GetProperties()) { string strNomConvivial = ""; object[] attribs; attribs = property.GetCustomAttributes(typeof(DynamicFieldAttribute), true); //si le champ a l'attribut dynamique, il a un nom convivial if (attribs.Length != 0) { strNomConvivial = ((DynamicFieldAttribute)attribs[0]).NomConvivial; } //Attribut TableField attribs = property.GetCustomAttributes(typeof(TableFieldPropertyAttribute), true); if (attribs.Length == 1 && !bRelationsOnly) { TableFieldPropertyAttribute attrib = (TableFieldPropertyAttribute)attribs[0]; if (attrib.IsInDb) //Ne prend que les champs qui sont dans la base de données { if (property.Name != "IdUniversel" || leType.GetCustomAttributes(typeof(NoIdUniverselAttribute), true).Length == 0) { if (property.PropertyType == typeof(string) && attrib.Longueur < 1) { throw (new Exception(I.T("The field attribute @1 of class @2 doesn't define a length|168", property.Name, leType.Name))); } bool bIsId = tableIdsDefinisDansTableAttribute[attrib.NomChamp] != null; CInfoChampTable info = new CInfoChampTable( attrib.NomChamp, property.PropertyType, attrib.Longueur, attrib.IsLongString, bIsId, attrib.NullAutorise && !bIsId, attrib.ExclureUpdateStandard, attrib.IsInDb); info.Propriete = property.Name; info.NomConvivial = strNomConvivial; if (property.GetCustomAttributes(typeof(IndexFieldAttribute), true).Length > 0) { info.IsIndex = true; } if (m_tableChamps[info.NomChamp] == null) { m_listeChamps.Add(info); m_tableChamps[info.NomChamp] = info; } if (bIsId) { tableIds[info.NomChamp] = info; } } } } //Attribut Relation if (bRelationsOnly) { m_bIsRelationsInitialisees = true; attribs = property.GetCustomAttributes(typeof(RelationAttribute), true); if (attribs.Length != 0) { RelationAttribute relAttrib = (RelationAttribute)attribs[0]; CStructureTable structureParente = GetStructure(CContexteDonnee.GetTypeForTable(relAttrib.TableMere)); if (relAttrib.TableMere == NomTable) //Pour les tables autoliées { structureParente = this; } //Si la structure parente est moi-même, les champs Id n'ont pas encore //été renseignés. Il y a donc un contrôle en moins sur les tables à lien récursif if (structureParente.ChampsId != null && relAttrib.ChampsFils.Length != relAttrib.ChampsParent.Length) { throw new Exception(I.T("The relation between the table @1 and the parental table @2 doesn't have the right number of link fields|169", NomTable, relAttrib.TableMere)); } int nIndexCle = 0; foreach (string strChamp in relAttrib.ChampsFils) { bool bIsId = tableIdsDefinisDansTableAttribute[strChamp] != null; CInfoChampTable info = new CInfoChampTable( strChamp, structureParente.GetChamp(relAttrib.ChampsParent[nIndexCle]).TypeDonnee, structureParente.GetChamp(relAttrib.ChampsParent[nIndexCle]).Longueur, false, bIsId, !relAttrib.Obligatoire, false, true); info.IsIndex = relAttrib.Index; //13/3/2005 : les deux lignes suivants avaient été enlevées. Pourquoi ? //En tout cas, moi j'en ai besoin pour pouvoir tester //Les attributs de la propriété //20/4/2005 //Ca avait été enlevé car le champ pointe sur le type de donnée //de la clé (un entier en général), c'est un champ qui ne doit pas être affiché //dans les listes de propriétés , c'est juste un champ de la table /*info.Propriete = property.Name; * info.NomConvivial = strNomConvivial;*/ /* 9/5/2005, si on souhaite trouver la propriété correspondantes, * il faut parcourir les relations et regarder les propriétés des relations * */ nIndexCle++; if (m_tableChamps[info.NomChamp] == null) { m_listeChamps.Add(info); m_tableChamps[info.NomChamp] = info; } if (tableIdsDefinisDansTableAttribute[strChamp] != null) { //Ce champ fait partie de la clé de l'objet tableIds[info.NomChamp] = info; } } CInfoRelation infoRelation = new CInfoRelation( relAttrib.TableMere, NomTable, relAttrib.ChampsParent, relAttrib.ChampsFils, relAttrib.Obligatoire, relAttrib.Composition, relAttrib.Index, relAttrib.PasserLesFilsANullLorsDeLaSuppression, relAttrib.DeleteEnCascadeManuel); infoRelation.IsInDb = relAttrib.IsInDb; infoRelation.IsClustered = relAttrib.IsCluster; infoRelation.NomConvivial = strNomConvivial; infoRelation.Propriete = property.Name; infoRelation.NePasClonerLesFils = relAttrib.NePasClonerLesFils; m_listeRelationsParentes.Add(infoRelation); } //Attribut RelationFille attribs = property.GetCustomAttributes(typeof(RelationFilleAttribute), true); if (attribs.Length != 0) { RelationFilleAttribute relFille = (RelationFilleAttribute)attribs[0]; PropertyInfo propParenteDansFille = relFille.TypeFille.GetProperty(relFille.ProprieteFille); if (propParenteDansFille == null) { throw new Exception(I.T("The @1 type defines a child relation on the child property @2.@3 which doesn't exist|170", leType.Name, relFille.TypeFille.Name, relFille.ProprieteFille)); } //Récupère les infos de la relation attribs = propParenteDansFille.GetCustomAttributes(typeof(RelationAttribute), true); if (attribs.Length != 1) { throw new Exception(I.T("The @1 type defines a child relation on the child property @2.@3 which doesn't define a parental relation|171", leType.Name, relFille.TypeFille.Name, relFille.ProprieteFille)); } RelationAttribute relInfo = (RelationAttribute)attribs[0]; //Récupère le nom de la table fille attribs = relFille.TypeFille.GetCustomAttributes(typeof(TableAttribute), true); if (attribs.Length != 1) { throw new Exception(I.T("The @1 type define a child relation on the @2 type which doesn't define a table|172", leType.Name, relFille.TypeFille.Name)); } object[] attr = property.GetCustomAttributes(typeof(DynamicChildsAttribute), false); if (attr.Length > 0) { strNomConvivial = ((DynamicChildsAttribute)attr[0]).NomConvivial; } CInfoRelation infoRelation = new CInfoRelation( NomTable, ((TableAttribute)attribs[0]).NomTable, relInfo.ChampsParent, relInfo.ChampsFils, relInfo.Obligatoire, relInfo.Composition, relInfo.Index, relInfo.PasserLesFilsANullLorsDeLaSuppression, relInfo.DeleteEnCascadeManuel); infoRelation.NomConvivial = strNomConvivial; infoRelation.Propriete = property.Name; infoRelation.NePasClonerLesFils = relInfo.NePasClonerLesFils; m_listeRelationsFilles.Add(infoRelation); } } } ///Relations TypeID foreach (RelationTypeIdAttribute relTypeId in CContexteDonnee.RelationsTypeIds) { if (relTypeId.IsAppliqueToType(leType)) { m_listeRelationsFillesTypeId.Add(relTypeId); } } //AddFields ( leType.BaseType, tableIdsDefinisDansTableAttribute, tableIds ); }
///////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Lit les dépendances filles du type de donné /// </summary> /// <returns></returns> private void ReadDependanceFille( string strPropriete, CListeObjetsDonnees lstSource, CListeObjetsDonnees.CArbreProps arbre, CInfoRelation relation, List <string> listePaquets) { CResultAErreur result = CResultAErreur.True; Type tpFille = null; PropertyInfo info = lstSource.TypeObjets.GetProperty(strPropriete); if (info == null) { return; } object[] attrs = info.GetCustomAttributes(typeof(RelationFilleAttribute), true); if (attrs == null || attrs.Length < 0) { return; } tpFille = ((RelationFilleAttribute)attrs[0]).TypeFille; DataTable table = lstSource.ContexteDonnee.GetTableSafe(lstSource.NomTable); //S'assure que la table fille est chargée lstSource.ContexteDonnee.GetTableSafe(relation.TableFille); string strKey = relation.RelationKey; DataColumn colDependance = table.Columns[strKey]; if (listePaquets == null) { listePaquets = lstSource.GetPaquetsPourLectureFils(relation.ChampsParent[0], colDependance); } int nNbPaquets = listePaquets.Count; //Lit les relations par paquet for (int nPaquet = 0; nPaquet < nNbPaquets; nPaquet++) { string strPaquet = (string)listePaquets[nPaquet]; if (strPaquet.Length > 0) { CListeObjetsDonnees listeFille = new CListeObjetsDonnees(lstSource.ContexteDonnee, tpFille); listeFille.Filtre = new CFiltreData(relation.ChampsFille[0] + " in " + strPaquet); if (arbre.Filtre.Length > 0) { listeFille.Filtre.Filtre += " and " + arbre.Filtre; } listeFille.ModeSansTri = true; listeFille.PreserveChanges = true; listeFille.AssureLectureFaite(); int nMax = Math.Min(lstSource.Count, (nPaquet + 1) * CListeObjetsDonnees.c_nNbLectureParLotFils); if (colDependance != null && arbre.Filtre.Length == 0) { //Indique que les lignes ont été lues for (int nRow = nPaquet * CListeObjetsDonnees.c_nNbLectureParLotFils; nRow < nMax; nRow++) { DataRow row = lstSource.View.GetRow(nRow); DataRowState oldState = row.RowState; row[colDependance] = true; if (oldState == DataRowState.Unchanged) { row.AcceptChanges(); } } } listeFille.ReadDependances(arbre); } } }
//------------------------------------- /// <summary> /// Retourne tous les fils qui étaient affecté à l'objet à l'époque /// </summary> /// <param name="objet"></param> /// <param name="relationFille"></param> /// <returns></returns> public int[] GetIdsChildsHistoriques(CObjetDonneeAIdNumerique objet, CInfoRelation relationFille) { Type tpFils = CContexteDonnee.GetTypeForTable(relationFille.TableFille); if (!typeof(CObjetDonneeAIdNumerique).IsAssignableFrom(tpFils)) { return(new int[0]); } CChampPourVersionInDb champFille = new CChampPourVersionInDb(relationFille.ChampsFille[0], ""); //Recherche toutes les modifications de la propriété fille CListeObjetsDonnees listeModifsFilles = new CListeObjetsDonnees(objet.ContexteDonnee, typeof(CVersionDonneesObjetOperation)); listeModifsFilles.Filtre = new CFiltreDataAvance( CVersionDonneesObjetOperation.c_nomTable, CVersionDonneesObjetOperation.c_champChamp + "=@1 and " + CVersionDonneesObjetOperation.c_champTypeChamp + "=@2 and " + CVersionDonneesObjet.c_nomTable + "." + CVersionDonneesObjet.c_champTypeElement + "=@3 and " + CVersionDonneesObjet.c_nomTable + "." + CVersionDonnees.c_nomTable + "." + CVersionDonnees.c_champTypeVersion + "=@4 and " + CVersionDonneesObjet.c_nomTable + "." + CVersionDonnees.c_champId + ">=@5", champFille.FieldKey, champFille.TypeChampString, tpFils.ToString(), (int)CTypeVersion.TypeVersion.Archive, Id); listeModifsFilles.Tri = CVersionDonneesObjetOperation.c_champId + " desc"; listeModifsFilles.ReadDependances("VersionObjet"); ArrayList lstFils = new ArrayList(); //Remplit la liste des fils avec les fils actuels //Récupère la liste de tous les fils actuels //et supprimés depuis. En effet, un element supprimé depuis cette version mais qui est //toujours lié à l'objet était donc lié à l'objet à l'époque C2iRequeteAvancee requete = new C2iRequeteAvancee(-1); requete.TableInterrogee = relationFille.TableFille; C2iChampDeRequete champDeRequete = new C2iChampDeRequete("ID", new CSourceDeChampDeRequete(objet.ContexteDonnee.GetTableSafe(relationFille.TableFille).PrimaryKey[0].ColumnName), typeof(int), OperationsAgregation.None, true); requete.ListeChamps.Add(champDeRequete); CFiltreData filtre = new CFiltreData(relationFille.ChampsFille[0] + "=@1 and (" + CSc2iDataConst.c_champIdVersion + " is null or " + CSc2iDataConst.c_champIdVersion + ">=@2)", objet.Id, Id); filtre.IgnorerVersionDeContexte = true; requete.FiltreAAppliquer = filtre; CResultAErreur result = requete.ExecuteRequete(objet.ContexteDonnee.IdSession); if (result) { foreach (DataRow row in ((DataTable)result.Data).Rows) { lstFils.Add(row[0]); } } foreach (CVersionDonneesObjetOperation data in listeModifsFilles) { if (data.GetValeur() is int && (int)data.GetValeur() == objet.Id) { if (!lstFils.Contains(data.VersionObjet.IdElement)) { lstFils.Add(data.VersionObjet.IdElement); } } else { lstFils.Remove(data.VersionObjet.IdElement); } } //Toutes les entités créées après la version ont également été ajoutées, //Donc n'y étaient pas if (lstFils.Count > 0) { StringBuilder builder = new StringBuilder(); foreach (int nId in lstFils) { builder.Append(nId.ToString()); builder.Append(","); } string strIds = builder.ToString(); strIds = strIds.Substring(0, strIds.Length - 1); requete = new C2iRequeteAvancee(-1); requete.TableInterrogee = CVersionDonneesObjet.c_nomTable; requete.FiltreAAppliquer = new CFiltreData( CVersionDonneesObjet.c_champIdElement + " in (" + strIds + ") and " + CVersionDonneesObjet.c_champTypeElement + "=@1 and " + CVersionDonneesObjet.c_champTypeOperation + "=@2 and " + CVersionDonnees.c_champId + ">=@3", tpFils.ToString(), CTypeOperationSurObjet.TypeOperation.Ajout, Id); requete.FiltreAAppliquer.IgnorerVersionDeContexte = true; requete.ListeChamps.Add(new C2iChampDeRequete("Id", new CSourceDeChampDeRequete(CVersionDonneesObjet.c_champIdElement), typeof(int), OperationsAgregation.None, true)); result = requete.ExecuteRequete(ContexteDonnee.IdSession); if (result) { foreach (DataRow row in ((DataTable)result.Data).Rows) { lstFils.Remove(row[0]); } } } return((int[])lstFils.ToArray(typeof(int))); }