2 votes

Mettre à jour une entité avec une clause supplémentaire

Je travaille actuellement sur une application multitenant basée sur des colonnes. J'ai ajouté le tenantId sur chaque entité avec une classe de base, et j'ai utilisé des filtres de requête qui correspondent parfaitement à mes besoins. J'ai également remplacé la méthode savechanges pour remplir la propriété tenantid sur les entités ajoutées en utilisant le changetracker.

Mais maintenant je suis coincé avec la mise à jour et la suppression. Pour autant que je sache, ef génère une clause where avec seulement la clé primaire, ce qui n'est pas très sûr pour moi, car je travaille sur un environnement api avec beaucoup de choses attachées/supprimées, et j'ai écrit beaucoup de entity.state = modified au lieu de faire une requête en premier, afin d'améliorer les performances.

Ma question est la suivante : comment ajouter un prédicat à une déclaration de mise à jour/suppression d'ef core ?

Je sais que je peux : 1. Faire une requête d'abord (et je suis sûr que vous allez me le recommander) 2. Faire de tenantid une partie d'une compositekey, mais cela serait vraiment pénible de refactorer tout mon code car les méthodes add/find/etc. ont besoin de clés primaires complètes.

Je serais vraiment reconnaissant à toute personne qui sait comment déclencher cela !

3voto

Ivan Stoev Points 1156

Option 3 :

Bien qu'il ne soit pas conçu pour cela, vous pouvez utiliser EF Core Contrôle optimiste de la concurrence pour effectuer ces contrôles de sécurité pour vous :

Sur les bases de données relationnelles, EF Core inclut une vérification de la valeur du jeton de simultanéité dans le champ WHERE clause de tout UPDATE ou DELETE déclarations. Après avoir exécuté les instructions, EF Core lit le nombre de lignes qui ont été affectées. Si aucune ligne n'est affectée, un conflit d'accès est détecté et EF Core lance la commande DbUpdateConcurrencyException .

L'idée est (1) de marquer le TenantId comme jeton de concours par [ConcurrencyCheck] ou IsConcurrencyToken() fluent API, et (2) dans votre SaveChanges de l'entreprise, définissez la TenantId avec la valeur de la propriété du locataire actuel Id non seulement pour les entités ajoutées, mais aussi pour les entités modifiées et supprimées.

En faisant cela, EF Core ajoutera quelque chose comme AND TenantId == @currentTenantId à UPDATE y DELETE qui ne réussiront que si le locataire actuel correspond à celui utilisé pour la création de l'entité.

L'inconvénient est le type/message d'exception, et le mélange avec les contrôles de concurrence existants s'ils sont utilisés.

Mise à jour : Le code pour les entités modifiées et supprimées à l'intérieur SaveChanges doit définir le OriginalValue de la TenantId et réinitialiser l'entrée de la propriété IsModified drapeau :

var tenantIdEntry = entityEntry.Property("TenantId");
tenantIdEntry.OriginalValue = CurrentTenantId;
tenantIdEntry.IsModified = false;

Le dernier n'est pas nécessaire si le TenantId est configuré avec AfterSaveBehavior = PropertySaveBehavior.Ignore comme expliqué dans Quelle est la meilleure façon d'effectuer des mises à jour partielles dans EF core et de ne jamais mettre à jour certaines propriétés ? .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X