Combinaison de code C # et de code de firebase database dans une spécification

Parfois, vous devez définir des règles de gestion et le modèle de spécification est un outil utile. Par exemple:

public class CanBorrowBooksSpec : ISpecification { public bool Satisfies(Customer customer) { return customer.HasLibraryCard && !customer.UnpaidFines.Any(); } } 

Cependant, je constate souvent que je dois «insérer» ces règles dans SQL pour améliorer les performances ou pour prendre en charge des éléments tels que des listes paginées d’enregistrements.

Il me rest alors à écrire deux fois le code des règles, une fois en code CLR et une fois en SQL (ou langage ORM).

Comment procédez-vous pour organiser un code comme celui-ci?

Il semble préférable que le code soit conservé dans la même classe. De cette manière, si le développeur met à jour les règles métier, il a moins de chance d’oublier de mettre à jour les deux ensembles de code. Par exemple:

 public class CanBorrowBooksSpec : ISpecification { public bool Satisfies(Customer customer) { return customer.HasLibraryCard && !customer.UnpaidFines.Any(); } public void AddSql(SsortingngBuilder sql) { sql.Append(@"customer.HasLibraryCard AND NOT EXISTS (SELECT Id FROM CustomerUnpaidFines WHERE CustomerId = customer.Id)"); } } 

Cependant, cela me semble plutôt moche, car nous mélangeons maintenant les préoccupations.

Une autre solution consisterait à utiliser une solution Linq-To-YourORM, car le code LINQ pourrait être exécuté sur une collection ou traduit en SQL. Mais j’ai constaté que de telles solutions sont rarement possibles, sauf dans les scénarios les plus sortingviaux.

Que faire?

Nous avons utilisé le modèle de spécification avec Entity Framework. Voici comment nous l’avons abordé

 public interface ISpecification { Expression> Predicate { get; } } public class CanBorrowBooksSpec : ISpecification { Expression> Predicate { get{ return customer => customer.HasLibraryCard && !customer.UnpaidFines.Any()} } } 

Ensuite, vous pouvez l’utiliser contre LINQ-to-Entities comme

 db.Customers.Where(canBorrowBooksSpec.Predicate); 

Dans LINQ-to-Objects comme

 customerCollection.Where(canBorrowBooksSpec.Predicate.Comstack());