0
votes

Pourquoi cela ne fonctionne-t-il pas correctement

Ce code est conçu pour effectuer un nettoyage après une réhydratation de la boîte aux lettres (à partir de Symantec Enterprise Vault). Nous prenons un index instantané des MessageId et ConversationId de tous les éléments de la boîte aux lettres avant la réhydratation.

Après la réhydratation, ce code

    if (string.Equals(item.ItemClass, "IPM.Note.EnterpriseVault.Shortcut", StringComparison.InvariantCulture) || ((existingIds.Any(x => x.ConversationId == item.ConversationId.ToString()) == false || (item.ItemClass == "IPM.Appointment" && existingIds.Any(x => x.MessageId == item.Id.ToString()) == false) && item.DateTimeReceived < snapshotDate)))
    {
        item.Delete(DeleteMode.HardDelete);
    }

devrait supprimer

  1. Tous les éléments dont la ItemClass est "IPM.Note.EnterpriseVault.Shortcut"
  2. Tous les éléments qui ont une ItemClass de "IPM.Appointment" où le Id ne se trouve pas dans la liste existingIds de MessageId s, sauf s'ils ont été reçus après le `snapshotDate
  3. Tout autre élément pour lequel ConversationId ne figure pas dans la liste existingIds , sauf s'ils ont été reçus après le snapshotDate .

Après avoir exécuté ce code, un utilisateur a signalé avoir perdu un e-mail reçu après le snapshotDate , il semble donc que je me trompe dans la déclaration if ! :( Quelqu'un pourrait-il me dire s'il vous plaît ce que j'ai mal (ou un moyen que je peux décomposer pour mieux le comprendre) et ce que ce code aura réellement fait pour que je puisse faire savoir à l'utilisateur ce qui a été perdu. Je sais lofical Les OR sont notoirement difficiles à écrire et je pense que j'ai fait une erreur avec les crochets quelque part mais je ne peux tout simplement pas le voir.


2 commentaires

Avez-vous besoin de supprimer l'élément qui a ItemClass de "IPM.Note.EnterpriseVault.Shortcut" et reçu après le snapshotDate?


@OxQ Il ne devrait y avoir aucun élément avec une ItemClass de "IPM.Note.EnterpriseVault.Shortcut" après le snapshotDate, mais ils peuvent également être supprimés.


3 Réponses :


1
votes

Je trouve que le moyen le plus simple de résoudre ce genre de problème est d'utiliser beaucoup de sauts de ligne et d'indentation. J'ajoute une pause et augmente l'indentation après chaque ( (sauf trivial () ), amène les ) correspondants sous leur paire correspondante et mets les opérateurs sur des lignes séparées entre les éléments qu'ils rejoignent:

if (
    string.Equals(
        item.ItemClass,
        "IPM.Note.EnterpriseVault.Shortcut", StringComparison.InvariantCulture
    )
    ||
    (
        (
            existingIds.Any(
                x => x.ConversationId == item.ConversationId.ToString()
            ) == false
            ||
            (
                item.ItemClass == "IPM.Appointment"
                &&
                existingIds.Any(
                    x => x.MessageId == item.Id.ToString()
                ) == false
            )
        )
        &&
        item.DateTimeReceived < snapshotDate
    )
)
{
    item.Delete(DeleteMode.HardDelete);
}

Je peux immédiatement repérer deux choses - il y a une paire de parenthèses qui contient juste une autre paire, et nous avons && code > et || se produisant au même "niveau", nous nous basons donc sur la priorité des opérateurs.

Je suppose que vous vouliez que le && soit à l'extérieur des parenthèses intérieures afin qu'il soit appliqué à la fois à la vérification de rendez-vous et aux identifiants existants. Par exemple. ceci à la place:

if (
    string.Equals(
        item.ItemClass,
        "IPM.Note.EnterpriseVault.Shortcut", StringComparison.InvariantCulture
    )
    ||
    (
        (
            existingIds.Any(
                x => x.ConversationId == item.ConversationId.ToString()
            ) == false
            ||
            (
                item.ItemClass == "IPM.Appointment"
                &&
                existingIds.Any(
                    x => x.MessageId == item.Id.ToString()
                ) == false
            )
            &&
            item.DateTimeReceived < snapshotDate
        )
    )
)
{
    item.Delete(DeleteMode.HardDelete);
}

(Une fois que vous avez confirmé que tout correspond à vos besoins, vous pouvez vous réduire à moins de lignes)


1 commentaires

Excellente astuce et bonne place avec les supports mal placés. Merci



1
votes

Je vous recommanderais de diviser si l'archivage en fonctions locales sera beaucoup plus facile à déboguer.

 if (IsShourtcut(item) || NotExistingAppItment(item) || ExistingConversation(item) && IsReceivedBeforSnapshot(item)) 
    {
            // to delete 
    }

bool IsShourtcut(Item item) => string.Equals(item.ItemClass, "IPM.Note.EnterpriseVault.Shortcut", StringComparison.InvariantCulture);
bool NotExistingAppItment(Item item) => item.ItemClass == "IPM.Appointment" && existingIds.All(x => x.MessageId != item.Id.ToString());
bool ExistingConversation(Item item) => existingIds.All(x => x.ConversationId != item.ConversationId.ToString();
bool IsReceivedBeforSnapshot(Item item) => item.DateTimeReceived < snapshotDate;


1 commentaires

Les fonctions locales sont une excellente idée. Pour quiconque lira ceci, vous devrez utiliser C # 7 ou supérieur pour les fonctions locales, mais si ce n'est pas une option, vous pouvez simplement utiliser des méthodes de la même classe. Je dois également souligner que, bien que ce soit une réponse extrêmement utile, elle ne correspond pas exactement à mon problème déclaré car elle ne prend pas en compte la date sur les rendez-vous existants.



0
votes

Les deux autres réponses à cette question ont été extrêmement utiles et j'ai voté en conséquence. Cependant, j'ai pensé publier ma solution finale à ce problème en s'inspirant de https://stackoverflow.com/a/61009776/470014 et https://stackoverflow.com/a/61008198/470014 , en s'appuyant particulièrement sur l'utilisation des fonctions locales comme recommandé par OxQ. J'ai maintenant écrit des tests unitaires (ce que j'aurais dû faire plus tôt) et ceux-ci passent tous en utilisant ma nouvelle méthode alors que cinq d'entre eux échouaient auparavant. Je pense que ce code correspond plus étroitement au problème déclaré et qu'il est assez simple à lire et à comprendre. J'ai dû utiliser des valeurs scalaires plutôt que l'ensemble de l'objet Item . Je peux donc effectuer un test unitaire car l'API gérée par les services Web Exchange n'utilise pas d'interfaces.

switch (itemClass)
{
    case "IPM.Note.EnterpriseVault.Shortcut":
        return true;
    case "IPM.Appointment":
        return NotExistingMessage() && IsReceivedBeforeSnapshot();
    default:
        return NotExistingConversation() && IsReceivedBeforeSnapshot();
}

bool NotExistingMessage() => existingIds.All(x => x.MessageId != messageId);
bool NotExistingConversation() => existingIds.All(x => x.ConversationId != conversationId);
bool IsReceivedBeforeSnapshot() => dateTimeReceived < uploadDate;

p >


0 commentaires