Traduction▲
Cet article est la traduction la plus fidèle possible de l'article original de Brad Abrams, Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 6: Data Transfer Objects (DTOs).
Data Transfer Objects - les objets de transfert de données (DTO)▲
J'ai reçu quelques questions intéressantes sur ma série jusqu'ici… Deux ou trois lecteurs ont noté qu'il n'était pas toujours une bonne idée de retourner les types DAL vers le client. Par exemple, dans la deuxième partie, j'ai retourné le type SuperEmployee défini par Entity Framework.
Par exemple, si vous changez votre back end d'EF à NHibernate il y aurait peut-être un certain effet de ceci dans la projection du client. Je peux aussi plus facilement contrôler comment l'entité apparait de manière exacte au client. Tant la forme des données ainsi que la validation, etc.
Pour répondre à ces préoccupations certaines personnes ont utilisé un schéma pour des Data Transfer Objects (DTO), ou comme certains les appellent, des objets client.
Pour démontrer combien il est facile d'utiliser ce schéma avec les services RIA et Silverlight 3 j'ai pris l'exemple de l'application des parties précédentes de la série et je l'ai modifié pour retourner des DTO plutôt que des types DAL.
La démo requiert les éléments suivants (tout est 100 % gratuit) :
- Visual Studio 2008 Express SP1 (qui comprend SQL Server 2008 Express) ;
- Silverlight 3 ;
- .NET RIA Services.
Vous pouvez, de plus, télécharger les fichiers de la démo complète et jeter un œil à l'application en cours d'exécution.
D'abord, j'ai défini mon type d'objet de transfert de données (DTO) sur le serveur. Idéalement, j'aurais pu faire le type de la forme que je voulais, selon ce qui est le mieux pour le client. Ensuite, j'ai ajouté les métadonnées de validation directement au type. Cette validation se passera du côté serveur ET client avant que vos méthodes DomainService soient appelées.
public
class
SuperEmployeeDTO
{
public
SuperEmployeeDTO
(
)
{
}
[ReadOnly(true)]
[Key]
public
int
EmployeeID {
get
;
set
;}
[RegularExpression(
"^(?:m|M|male|Male|f|F|female|Female)$"
,
ErrorMessage =
"Gender must be 'Male' or 'Female'"
)]
public
string
Gender {
get
;
set
;}
[Range(
0
,
10000
,
ErrorMessage =
"Issues must be between 0 and 1000"
)]
public
Nullable<
int
>
Issues {
get
;
set
;}
public
Nullable<
DateTime>
LastEdit {
get
;
set
;}
[Required]
[StringLength(
100
)]
public
string
Name {
get
;
set
;}
public
string
Origin {
get
;
set
;}
public
string
Publishers {
get
;
set
;}
public
string
Sites {
get
;
set
;}
}
Remarquez, j'ai quelques attributs de validation sur ce type, donc je suppose que techniquement, ce n'est pas purement un DTO… Si vous avez besoin d'un DTO pur, vous pouvez bien sûr mettre ces attributs sur le client…
Puis mes méthodes DomainService mappent simplement des types DAL au DTO lorsque les données sortent et du DTO aux types DAL lorsque les données entrent.
public
IQueryable<
SuperEmployeeDTO>
GetSuperEmployeeDTOs
(
)
{
return
this
.
Context.
DBSuperEmployeeSet
.
Where
(
emp=>
emp.
Issues>
100
)
.
OrderBy
(
emp=>
emp.
EmployeeID)
.
Select (
emp=>
new
SuperEmployeeDTO (
) {
EmployeeID =
emp.
EmployeeID,
Gender =
emp.
Gender,
Issues =
emp.
Issues,
LastEdit =
emp.
LastEdit,
Name =
emp.
Name,
Origin =
emp.
Origin,
Publishers =
emp.
Publishers,
Sites =
emp.
Sites
}
);
}
public
void
UpdateSuperEmployee
(
SuperEmployeeDTO superEmployee)
{
var
orgEmp =
this
.
ChangeSet.
GetOriginal
(
superEmployee);
var
DbEmp =
this
.
Context.
DBSuperEmployeeSet
.
Where
(
e =>
e.
EmployeeID ==
superEmployee.
EmployeeID)
.
FirstOrDefault
(
);
if
(
orgEmp.
Name !=
superEmployee.
Name) DbEmp.
Name =
superEmployee.
Name;
if
(
orgEmp.
Gender !=
superEmployee.
Gender) DbEmp.
Gender =
superEmployee.
Gender;
if
(
orgEmp.
Issues !=
superEmployee.
Issues) DbEmp.
Issues =
superEmployee.
Issues;
if
(
orgEmp.
LastEdit !=
superEmployee.
LastEdit) DbEmp.
LastEdit =
superEmployee.
LastEdit;
if
(
orgEmp.
Origin !=
superEmployee.
Origin) DbEmp.
Origin =
superEmployee.
Origin;
if
(
orgEmp.
Publishers !=
superEmployee.
Publishers) DbEmp.
Publishers =
superEmployee.
Publishers;
if
(
orgEmp.
Sites !=
superEmployee.
Sites) DbEmp.
Sites =
superEmployee.
Sites;
}
Remarquez ici que nous devons obtenir la valeur d'origine en retour. C'est-à-dire la valeur que le client a vue en dernier… ce qui est important pour nous afin de savoir quel élément a réellement changé sur le client. Sans cela, nous aurions à supposer que TOUS les éléments ont changé et cela créerait beaucoup plus de conflits de données. De cette façon, nous ne modifions le modèle EF qu'avec les éléments qui ont changé.
Enfin, j'ai besoin de mettre à jour quelques noms sur le client parce que j'ai modifié le nom de SuperEmployee à SuperEmployeeDTO… mais ceci est très facile à faire.
Exécutez l'application et elle apparait comme on l'avait laissée dans la deuxième partie, mais cette fois-ci toutes les données sont transmises via DTO ce qui vous donne plus de souplesse.
Conclusion▲
Ceci conclut donc la sixième partie de cette série d'articles sur le développement d'applications métier avec Silverlight 3 et .NET RIA Services. La septième partie sera consacrée au magasin de données basé sur ADO.NET Data Services.
Remerciements▲
Je tiens ici à remercier Brad Abrams de nous avoir autorisés à traduire son article.
Je remercie également ClaudeLELOUP pour sa relecture et ses propositions.