Questions sur l'architecture 3-tiers !

[Désolée, j’ai posté le sujet sur msdn et j’ai la flemme de traduire… Si ça pose problème, je traduirais. ^^]

Hello every one !

I’m developing an application in C# based on 3-tiers architecture using the Windows Enterprise Library.
I have some questions for you ! ^^

First, I have two tables : PRODUCT_TYPE (id_type, name);
PRODUCT (id_product, name, id_type#);
In my Business Object Layer, I want to create two classes : PRODUCT_TYPE and PRODUCT.
Should I respect the database for writing them ? Should I put a property id_type in my class PRODUCT or should I put an instance of PRODUCT_TYPE ? What’s the best way to do ? What do you do in your application ?

Then I have a question about my Data Access Layer. When I added an employee to my database, I can also (but is not an obligation) reference his contract (I have two table : CONTRACT and EMPLOYEE).
So, in my DAL, I have two methods : CreateEmployee(Employee anEmployee) and
CreateContrat(Contract contract, Employee theEmployee).
I would like to create a new methods called CreateEmpployeeWithContract wich insert an employee and his contract, in the same time…
To do that, I would like to use transaction.
I don’t really know how I should do…
Do I create a method in my Business Logic Layer and create the transaction in this then I call the two function CreateEmployee and CreateContract ? Or, do I make a method in the DAL wich execute the SQL statement with the transaction ?

Can a BLL have access to the transaction ? Can she open a connection to a database ? I guess not… What do you think anout it ?
How do you do ?

Thank you very much for answer me… I am a bit lost ! ^^

This is a post for GloP !

All the response in English ?

[quote=« ZGoblin, post:2, topic: 50813 »]This is a post for GloP !


All the response in English ?
[/quote]

En français c’est bon aussi ! ^^ C’est juste que j’ai copié le sujet que j’ai posté ce matin sur MSDN (pas de réponse) mais que j’ai eu la flemme de traduire ! …

Mais, je peux traduire si vous voulez :smiley: !

Personnellement, j’apprécierai que tu fasses l’effort de traduire :smiley:

�?tant donné que cela va nous prendre certainement plus de temps pour te répondre que ton copier/coller, la moindre des choses serait de nous faciliter le travail au maximum.

Surtout qu’à priori ton problème va déclencher plus de discussion que deux simples lignes de code.

Ok, je traduit. ^^

Bonjour tout le monde !

Je suis en train de développer une application en C# basée sur l’architecture 3-tiers en utilisant Windows Enterprise Library.
J’ai queqlques questions pour vous ! ^^

Tout d’abord, j’ai deux tables : PRODUCT_TYPE (id_type, name);
PRODUCT (id_product, name, id_type#);

Dans ma Business Object Layer, je veux créer 2 classes : PRODUCT_TYPE and PRODUCT.
Est-ce que je dois respecter la base de données et mettre la propriété id_type dans ma classe PRODUCT ou est-ce que je dois mettre une instance de PRODUCT_TYPE dans PRODUCT ? C’est quoi le mieux ? Comment vos faites dans vos applications ?

J’ai aussi une question pour ma Data Access Layer. Quand j’ajoute un Employé dans ma base de données, je peux aussi (mais c’est pas une obligation) référencer son contrat (j’ai deux tables : CONTRACT and EMPLOYEE).

Dons, dans ma DAL, j’ai 2 méthodes : CreateEmploye(Employe unEmploye) et CreateContrat(Contrat contrat, Employe unEmploye).
J’aimerais créer une méthode CreateEmployeAvecContrat qui insèrerait dans ma base de données un employé et son contrat en même temps.
Pour faire ça, je pensais utiliser les transactions SQL (commit et rollback).
Je ne sais pas comment je dois faire…
Est-ce que je crée une méthode dans ma Business Logic Layer qui crée la transaction et qui appelle CreateEmploye et CreateContrat (en passant la transaction en paramètre) ? Ou est-ce que je fais dans ma DAL la méthode CreateEmployeAvecContrat qui exécutera la requête et s’occupera de gérer la transaction ?

Est-ce qu’un BLL peut avoir accès à la transaction SQL (dans le cas où je la créerais dans la BLL) ? Est-ce qu’elle peut ouvrir une connection à une base de données ? Je ne pense pas…
Qu’est ce que vous en pensez ? Comment vous feriez ?

Merci beaucoup de me répondre… je suis un peu perdue ! ^^

Et voilà !

J’imagine que tu parles de MS Enterprise Library 4.1

[quote]Tout d’abord, j’ai deux tables : PRODUCT_TYPE (id_type, name);
PRODUCT (id_product, name, id_type#);

Dans ma Business Object Layer, je veux créer 2 classes : PRODUCT_TYPE and PRODUCT.
Est-ce que je dois respecter la base de données et mettre la propriété id_type dans ma classe PRODUCT ou est-ce que je dois mettre une instance de PRODUCT_TYPE dans PRODUCT ? C’est quoi le mieux ? Comment vos faites dans vos applications ?[/quote]
La méthode la plus respectueuse de la modélisation objet, mais qui nécessite l’emploi d’un ORM (ADO.NET Entity Framework, LinqToSql, NHibernate, etc. mais pas Data Access Application Block) serait celle qui te permettrait d’utiliser les propriétés et masquerait les IDs.

La méthode la plus rapide, demandant le moins de code d’infrastructure serait de laisser les identifiants numériques et de créer ces objets en tant que “conteneurs de données”. Et là je te renvoie sur les “Anemic Domain Model” et les problèmes de conception que cela soulève.

[quote]J’ai aussi une question pour ma Data Access Layer. Quand j’ajoute un Employé dans ma base de données, je peux aussi (mais c’est pas une obligation) référencer son contrat (j’ai deux tables : CONTRACT and EMPLOYEE).

Dons, dans ma DAL, j’ai 2 méthodes : CreateEmploye(Employe unEmploye) et CreateContrat(Contrat contrat, Employe unEmploye).
J’aimerais créer une méthode CreateEmployeAvecContrat qui insèrerait dans ma base de données un employé et son contrat en même temps.
Pour faire ça, je pensais utiliser les transactions SQL (commit et rollback).
Je ne sais pas comment je dois faire…
Est-ce que je crée une méthode dans ma Business Logic Layer qui crée la transaction et qui appelle CreateEmploye et CreateContrat (en passant la transaction en paramètre) ? Ou est-ce que je fais dans ma DAL la méthode CreateEmployeAvecContrat qui exécutera la requête et s’occupera de gérer la transaction ?

Est-ce qu’un BLL peut avoir accès à la transaction SQL (dans le cas où je la créerais dans la BLL) ? Est-ce qu’elle peut ouvrir une connection à une base de données ? Je ne pense pas…
Qu’est ce que vous en pensez ? Comment vous feriez ?[/quote]
Deux méthodes là aussi :

  • Méthode rapide, tu découvres TransactionScope, disponible dans System.Transaction et qui permet de gérer une transaction automatique qui sera utilisé par ta DAL. Tu gardes tes deux méthodes de DAL et tu démarres un TransactionScope dans ton code BLL.

using (var scope = new TransactionScope()) { dal.CreateEmployee(employee); dal.CreateContract(contract, employee) scope.Commit(); }

  • Méthode plus poussée : tu t’intéresses au pattern UnitOfWork qui masque l’utilisation du TransactionScope pour le rendre plus générique (et moins lié à l’accès aux données.

[code]using (IUnitOfWork unitOfWork = UnitOfWork.Create())
{
dal.CreateEmployee(employee);
dal.CreateContract(contract, employee)

unitOfWork.Complete();
}[/code]

La nuance avec l’exemple précédent, c’est que c’est toi qui décide ce que tu souhaites faire dans ton commit. Pour encapsuler ton premier développement, tu appelles scope.Complete(). Dans un autre cas (utilisation d’un ORM), tu valides les opérations sur la session (NHibernate) ou le DataContext (LinqToSql), etc. sans modifier ton code métier.

Tout cela devrait te fournir assez de mots-clés pour quelques recherches Google.

Merci pour toutes ces précisions Styx31 !
Je vais regarder ça de près.
A vrai dire, ce qui m’intéresse surtout c’est cette histoire de transactionScope.
J’ai fait un test mais j’ai une erreur bizarre que le premier ExecuteNonQuery. (You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘XA BEGIN ‘c02dab7b-d702-6454-b6be-33cfcec6a44e,-836f-6c9da2149e1a’’ at line 1)

Voici mon code :

using (TransactionScope t = new TransactionScope()) { Database d = DatabaseFactory.CreateDatabase(); DbCommand c = d.GetSqlStringCommand("INSERT INTO privileges(alias) VALUES('plop')"); d.ExecuteNonQuery(c); DbCommand c2 = d.GetSqlStringCommand("INSERT INTO privileges(alias)VALUES('plop2')"); d.ExecuteNonQuery(c2); t.Complete(); }

Pour moi il n’y a aucune raison que ça ne fonctionne pas…

Je pense que c’est une incompatibilité avec MySQL… J’ai la version 4. Et, je sais que si j’enlève le using, mon code d’INSERT INTO fonctionne…
Donc, je pense que le problème c’est MySQL. Si vous pensez à autre chose, dites le moi ! ^^

Si j’arrivais à faire marcher ça, ce serait un bon point !

Ouaip, je suis pas super certain que MySql et MsDtc (Dtistributed Transaction Coordinator, le truc magique derriere TransactionScope qui petmet entre autre de creer des transaction cross-instances de base de donnees) marchent super bien ensemble (loin de moi l’idee de dire que MySql c’est tout pourri, hein, mais plutot qu’ils se fichent pas mal de l’environement MS).

Par contre fait un peu gaffe quand meme, tu devrais fermer tes connexions / datareaders / commands etc. parce que la tu vas exploser ton connection pool a vitesse grand V !. (using(var db = truc){ } est ton amis aussi).

Merci pour ta réponse! C’est vraiment dommage que les transactionscope ne marche pas…
Ca m’aurait vraiment simplifié la vie !

Oui, je sais que rien n’est fermé… ^^ C’est juste un petit exemple que je me suis fait.

J’en sais un peu plus sur mon erreur au niveau du TransactionScope.
L’erreur (You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘XA BEGIN ‘c02dab7b-d702-6454-b6be-33cfcec6a44e,-836f-6c9da2149e1a’’ at line 1) se produit à l’ouverture de ma connection MySQL…

Peut être que cela vous aiguillera pour m’aider ? ^^