Modèle de données (ADO.NET Data Services Framework)
ADO.NET Data Services prend en charge en natif les modèles ADO.NET Entity Framework et fournit une extension par laquelle un modèle de données peut être défini en utilisant des objets CLR (common language runtime). La terminologie du modèle EDM (Entity Data Model), spécifiquement le langage CSDL (conceptual schema definition language) et des termes tels que EntitySet, EntityType, Property, Association, AssociationSet, etc. sont utilisés pour décrire les données déployées par ADO.NET Data Services Framework. Pour obtenir la définition de ces termes, consultez Terminologie d'ADO.NET Data Services Framework. Pour plus d'informations sur CSDL, consultez Spécifications EDM.
En réduisant les sources de données en une seule grammaire et des conventions URI uniformes, ADO.NET Data Services peut déployer des représentations cohérentes des données quelles que soient les sources de données sous-jacentes. Lorsqu'un modèle Entity Framework est utilisé, la configuration d'un service de données est insignifiante. Pour les modèles basés sur le langage CLR, un mappage entre les objets CLR et les types EDM a été défini.
Modèle de données EDM
Dans le modèle EDM (Entity Data Model), ADO.NET Data Services interagit avec la couche Object Services de Entity Framework, qui est un contexte programmable en langage CLR. Même si le contexte de programmation et le modèle conceptuel peuvent être conçus manuellement, l'approche recommandée consiste à utiliser les Outils Entity Data Model intégrés à Microsoft Visual Studio 2008 à compter de SP1.
Pour obtenir un exemple d'utilisation des outils EDM et Entity Framework, consultez Démarrage rapide de Data Service (ADO.NET Data Services Framework).
Modèle de données basé sur CLR
ADO.NET Data Services opère en convertissant les demandes URI en opérations sur les données qui sont adressées par la syntaxe d'URI. Lorsque le modèle de données est basé sur Entity Framework, les URI sont convertis en appels de méthode Object Services. Entity Framework ObjectContext déploie des jeux de données basés sur ObjectQuery<T> et ObjectQuery<T> implémente IQueryable<T>.
Toute technologie ou fournisseur de données qui déploie ses données en implémentant un dérivé de IQueryable peut être déployé comme un service de données ADO.NET. La méthode d'extension AsQueryable , disponible depuis .NET Framework 3.5, peut être utilisée avec des objets qui implémentent IEnumerable<T>. Toutes les classes dans .NET Framework qui implémentent IEnumerable<T> peuvent être étendues en appelant la méthode d'extension AsQueryable. Cela signifie que la plupart des listes, tableaux et collections peuvent être déployés efficacement comme ADO.NET Data Services.
Les requêtes LINQ fonctionnent également avec des sources de données qui implémentent IEnumerable<T> ou IQueryable<T>. Lorsque le modèle de données sous-jacent pour ADO.NET Data Service est défini en utilisant les objets CLR, les URI de demande sont convertis en requêtes LINQ. Un mappage complet est défini entre les objets CLR et les ressources d'ADO.NET Data Services. Le mappage des objets CLR aux jeux d'entités ADO.NET permet à ADO.NET Data Services de déployer toutes les sources de données qui peuvent être lues dans la mémoire en tant que tableau, liste ou collection.
Exemple 1 : Classes CLR à des ressources ADO.NET Data Service
L'exemple suivant montre le mappage entre les constructions de CLR et les ressources ADO.NET Data Services. Les classes implémentant l'interface IQueryable<T> sont représentées sous la forme de jeux d'entités.
L'exemple suivant utilise la méthode d'extension AsQueryable pour convertir un tableau de Customers
au format IQueryable<T>. Le tableau de Customers
est ici construit simplement mais les données d'application peuvent être lues depuis presque toutes les sources.
L'exemple de code porte une annotation pour indiquer comment les types CLR mappent aux types de ressources ADO.NET Data Services.
namespace Accounting // Namespace
{
public class DataModel // EntityContainer
{
public IQueryable<Customer> Customers // EntitySet
{
get
{
return new Customer[] { new Customer(1, "name1"),
new Customer(2,
"name2") }.AsQueryable<Customer>();
}
}
}
public class Customer // EntityType
{
private int _ID;
private string _name;
private Address _address;
public Customer(int i, string name)
{
_ID = i;
_name = name;
_address.Line1 = "Line" + i;
_address.Line2 = "Line" + i;
}
[DataWebKeyAttribute]
public int ID // Entity Type Key
{
get { return _ID; }
}
public string CustName // Property
{
get { return _name; }
}
public Address Address // Property
{
get { return _address; }
}
}
public struct Address // ComplexType
{
private string line1;
private string line2;
public string Line1 // Property
{
get { return this.line1; }
set { this.line1 = value; }
}
public string Line2 // Property
{
get { return this.line2; }
set { this.line2 = value; }
}
}
}
Lors du mappage d'une entité CLR à une ressource ADO.NET Data Services, la casse du nom CLR est copiée par la ressource ADO.NET Data Services associée. Les types CLR qui correspondent aux ressources ADO.NET Data Services, comme indiqué par les commentaires dans le code précédent, sont décrits dans la liste suivante.
Conteneurs d'entités et jeux d'entités
Une seule classe CLR publique (C1) dans un espace de noms défini explicitement est utilisée pour définir tous les jeux d'entités de niveau supérieur dans le modèle. Les ressources de niveau supérieur sont accessibles à l'aide du premier segment de chemin d'accès dans un URI.
L'espace de noms dans lequel la classe C1 existe est l'espace de noms qui identifie C1 comme le conteneur d'entités. Ceci est constant même si C1 est un type dérivé.
Le nom de la classe C1 représente le conteneur d'entités. Un seul conteneur d'entités peut être défini pour l'espace de noms. Ceci est constant même si C1 est un type dérivé.
Chaque jeu d'entités doit être représenté comme une propriété publique (P1) de la classe C1 avec un type de retour de IQueryable<T>. Zéro ou plusieurs propriétés peuvent exister sur la classe C1 ou bien, si la classe est un type dérivé, sur une de ses classes parentes.
T représente le type d'entité dans le jeu d'entités.
T doit avoir une propriété appropriée pour être une clé d'entité pour que la propriété C1 puisse être prise en compte comme un jeu d'entités. Si aucune propriété de clé appropriée n'existe, la propriété P1 est ignorée et C1 n'est pas prise en compte pour représenter un jeu d'entités par le service de données ADO.NET Data Services.
Le même type T ne peut pas être retourné par plusieurs propriétés sur la classe C1 ou une classe parente de C1. Cette définition de modèle basée sur le langage CLR ne prend pas en charge l'inclusion du même type d'entité, dans ce cas représenté par la classe T, dans des jeux d'entités multiples. Des jeux d'entités multiples par type peuvent être implémentés dans Entity Framework mais non en tant que classes déployées par ADO.NET Data Services.
Types d'entité, propriétés et liens de navigation
Une classe CLR publique (C1) représente un type d'entité.
Pour être reconnue comme un type d'entité, une classe doit avoir une propriété ou des propriétés qui représentent la clé du type. Une telle propriété ou groupe de propriétés devient la clé pour le type d'entité. Les règles pour les propriétés qui représentent une clé sont :
Propriété publique nommée ID.
Propriété publique nommée <className>ID.
Les propriétés publiques marquées par l'attribut DataWebKeyAttribute attribut.
Si une classe contient une propriété ou un groupe de propriétés qui sont marqués par DataWebKeyAttribute, ces propriétés sont utilisées comme la clé et les deux premières règles sont ignorées. Si aucune propriété ne contient l'attribut alors ces propriétés correspondant aux deux premières règles déterminent la propriété clé du type d'entité. Si plusieurs propriétés correspondent aux règles, le type d'entité a, par définition une clé composite.
Si la classe C1 fait partie d'une hiérarchie, la hiérarchie des classes est traduite en hiérarchie des types d'entités en appliquant les règles suivantes :
- La classe CLR la plus proche de la racine de la hiérarchie des classes qui inclut une propriété de clé valide devient la racine de la hiérarchie des types d'entités. Si la classe C1 n'est pas la racine de la hiérarchie de classe CLR dans laquelle elle participe, alors les propriétés déclarées par les classes au-dessus de C1 dans la hiérarchie sont supposées être déclarées par C1.
Chaque propriété (P) déclarée par la classe C1 est traduite en une propriété sur le type d'entité si la propriété CLR est conforme à toutes les conventions suivantes :
La propriété CLR doit avoir une étendue publique.
La propriété CLR doit implémenter une méthode get pour la propriété.
La propriété CLR ne doit pas être un indexeur.
Si le type de retour de la propriété P est un type primitif et que le type correspond à un type EDM, la propriété doit être représentée comme une propriété. Consultez Types de contenu ADO.NET Data Services pour un mappage des types EDM aux types CLR.
Si le type de retour de la propriété P est un type de référence et que le type ou un de ses objets parents, si c'est un type dérivé, représente un type d'entité, alors P représente un lien de navigation (1-1).
Si le type de retour de la propriété P est IEnumerable<T> et que T représente un type d'entité, alors P représente un lien de navigation de type un-à-plusieurs.
Si le type de retour de la propriété P est un type de valeur, alors P représente un type complexe.
Types complexes
Un type de valeur CLR public (V1) représente un type complexe.
Chaque propriété du type de valeur V1 est traduit en une propriété d'un type complexe. Les types complexes suivent des règles similaires aux types d'entités pour déterminer si une propriété CLR sera mappée à une propriété.
La propriété CLR doit avoir une étendue publique.
La propriété CLR doit implémenter une méthode Get pour la propriété.
La propriété CLR ne doit pas être un indexeur.
Si le type de retour de la propriété P est un type de référence et que le type ou un de ses objets parents, si c'est un type dérivé, représente un type d'entité, P représente un lien de navigation un-à-un.
Exemple 2 : Classes CLR à des ressources ADO.NET Data Service
L'exemple suivant montre des classes CLR qui incluent un héritage utilisé pour implémenter des types de ressources ADO.NET Data Services.
namespace Accounting
{
public class DataModel
{
public IQueryable<Customer> Customers
{
get
{
return new Customer[] { new Customer(1, "name1"),
new Customer(2, "name2") }.AsQueryable<Customer>();
}
}
public IQueryable<Order> Orders
{
get
{
return new Order[] { new Order(1, "order1"),
new Order(2, "order2") }.AsQueryable<Order>();
}
}
}
public class DerivedDataModel : DataModel
{
public IQueryable<HumanResources.Employee> Employees
{
get { return new HumanResources.Employee[] { new
HumanResources.Employee(1, "EmpName1"), new
HumanResources.Employee(2, "EmpName2")
}.AsQueryable<HumanResources.Employee>();
}
}
}
public class Person
{
protected int _ID;
public Person() { }
public Person(int i)
{
_ID = i;
}
[DataWebKeyAttribute]
public int ID
{
get { return _ID; }
}
}
public class Customer : Person
{
private string _name;
private Address _address;
List<Order> _orders;
public Customer(int i, string name)
{
_ID = i;
_name = name;
_orders = new List<Order>();
if (i == 1) { _orders.Add(new Order(1, "order1")); }
if (i == 2) { _orders.Add(new Order(2, "order2")); }
_address.Line1 = "Line" + i;
_address.Line2 = "Line" + i;
}
public string CustName
{
get { return _name; }
}
public Address Address
{
get { return _address; }
}
public IList<Order> Orders
{
get { return _orders; }
}
}
public class Order
{
private int _ID;
private string _name;
public Order(int i, string name)
{
_ID = i;
_name = name;
}
[DataWebKeyAttribute]
public int OrderKey
{
get { return _ID; }
}
public string OrderName
{
get { return _name; }
}
}
public struct Address
{
private string line1;
private string line2;
public string Line1
{
get { return this.line1; }
set { this.line1 = value; }
}
public string Line2
{
get { return this.line2; }
set { this.line2 = value; }
}
}
}
namespace HumanResources
{
public class Employee
{
private int _ID;
private string _name;
public Employee(int i, string name)
{
_ID = i;
_name = name;
}
public int ID
{
get { return _ID; }
}
public string EmpName
{
get { return _name; }
}
}
}
Prise en charge écriture/mise à jour
Pour activer la prise en charge de la création, de la mise à jour et de la suppression sur un modèle de données CLR, la classe qui modélise les jeux d'entités de niveau supérieur doit implémenter l'interface IUpdatable. En référence à l'exemple 2, les objets CLR aux ressources ADO.NET Data Services Framework ci-dessus, la classe Accounting.DataModel devra implémenter l'interface IUpdatable.
Voir aussi
Concepts
Spécifications d'ADO.NET Data Service