Partager via


Procédure : créer un service de données à l'aide d'une source de données LINQ to SQL (WCF Data Services)

Services de données WCF expose les données d'entité comme un service de données. Le fournisseur de réflexion vous permet de définir un modèle de données basé sur toute classe exposant des membres qui retournent une implémentation IQueryable<T>. Pour pouvoir effectuer des mises à jour des données dans la source de données, ces classes doivent également implémenter l'interface IUpdatable. Pour plus d'informations, consultez Fournisseurs de services de données (WCF Data Services). Cette rubrique vous montre comment créer des classes LINQ to SQL qui accèdent à l'exemple de base de données Northwind à l'aide du fournisseur de réflexion, et comment créer le service de données basé sur ces classes de données.

Pour ajouter des classes LINQ to SQL à un projet.

  1. À partir d'une application Visual Basic ou C#, dans le menu Projet, cliquez sur Ajouter un nouvel élément.

  2. Cliquez sur le modèle Classes LINQ to SQL.

  3. Modifiez le nom en Northwind.dbml.

  4. Cliquez sur Ajouter.

    Le fichier Northwind.dbml est ajouté au projet et le Concepteur Objet/Relationnel (Concepteur O/R) s'ouvre.

  5. Dans Serveur/Explorateur de bases de données, sous Northwind, développez Tables et faites glisser la table Customers vers le Concepteur Objet/Relationnel (Concepteur O/R).

    Une classe d'entité Customer est créée et apparaît dans l'aire de conception.

  6. Répétez l'étape 6 pour les tables Orders, Order_Details et Products.

  7. Cliquez avec le bouton droit sur le nouveau fichier .dbml qui représente les classes LINQ to SQL et cliquez sur Afficher le code.

    Cela crée une nouvelle page code-behind nommée Northwind.cs qui contient une définition de classe partielle pour la classe qui hérite de la classe DataContext, dans ce cas NorthwindDataContext.

  8. Remplacez le contenu du fichier de code Northwind.cs par le code suivant. Ce code implémente le fournisseur de réflexion en étendant les classes de données et DataContext générés par LINQ to SQL :

    Imports System.ComponentModel
    Imports System.Collections
    Imports System.Linq
    Imports System.Reflection
    Imports System.Data.Linq
    Imports System.Data.Linq.Mapping
    Imports System.Data.Services
    Imports System.Data.Services.Common
    
    ' Define the key properties for the LINQ to SQL data classes.
    <DataServiceKeyAttribute("CustomerID")> _
    Partial Public Class Customer
    End Class
    <DataServiceKeyAttribute("ProductID")> _
    Partial Public Class Product
    End Class
    <DataServiceKeyAttribute("OrderID")> _
    Partial Public Class Order
    End Class
    <DataServiceKeyAttribute("OrderID", "ProductID")> _
    Partial Public Class Order_Detail
    End Class
    #Region "IUpdatable implementation"
    ' Define the IUpdatable implementation for LINQ to SQL.
    Partial Public Class NorthwindDataContext
        Implements IUpdatable
        ' Creates an object in the container.
        Function CreateResource(ByVal containerName As String, ByVal fullTypeName As String) _
            As Object Implements IUpdatable.CreateResource
    
            Dim t = Type.GetType(fullTypeName, True)
            Dim table = GetTable(t)
            Dim resource = Activator.CreateInstance(t)
            table.InsertOnSubmit(resource)
            Return resource
        End Function
        ' Gets the object referenced by the resource.
        Function GetResource(ByVal query As IQueryable, ByVal fullTypeName As String) As Object _
         Implements IUpdatable.GetResource
            Dim resource = query.Cast(Of Object)().SingleOrDefault()
    
            ' fullTypeName can be null for deletes
            If fullTypeName IsNot Nothing AndAlso resource.GetType().FullName <> fullTypeName Then
                Throw New ApplicationException("Unexpected type for this resource.")
            End If
            Return resource
        End Function
        ' Resets the value of the object to its default value.
        Function ResetResource(ByVal resource As Object) As Object _
            Implements IUpdatable.ResetResource
            Dim t = resource.GetType()
            Dim table = Mapping.GetTable(t)
            Dim dummyResource = Activator.CreateInstance(t)
            For Each member In table.RowType.DataMembers
    
                If Not member.IsPrimaryKey AndAlso Not member.IsDeferred AndAlso _
                    Not member.IsAssociation AndAlso Not member.IsDbGenerated Then
                    Dim defaultValue = member.MemberAccessor.GetBoxedValue(dummyResource)
                    member.MemberAccessor.SetBoxedValue(resource, defaultValue)
                End If
                Next
            Return resource
        End Function
        ' Sets the value of the given property on the object.
        Sub SetValue(ByVal targetResource As Object, ByVal propertyName As String, _
                     ByVal propertyValue As Object) Implements IUpdatable.SetValue
            Dim table = Mapping.GetTable(targetResource.GetType())
            Dim member = table.RowType.DataMembers.Single(Function(x) x.Name = propertyName)
            member.MemberAccessor.SetBoxedValue(targetResource, propertyValue)
        End Sub
        ' Gets the value of a property on an object.
        Function GetValue(ByVal targetResource As Object, ByVal propertyName As String) _
        As Object Implements IUpdatable.GetValue
            Dim table = Mapping.GetTable(targetResource.GetType())
            Dim member = _
            table.RowType.DataMembers.Single(Function(x) x.Name = propertyName)
            Return member.MemberAccessor.GetBoxedValue(targetResource)
        End Function
        ' Sets the related object for a reference.
        Sub SetReference(ByVal targetResource As Object, ByVal propertyName As String, _
                         ByVal propertyValue As Object) Implements IUpdatable.SetReference
            CType(Me, IUpdatable).SetValue(targetResource, propertyName, propertyValue)
        End Sub
    ' Adds the object to the related objects collection.
        Sub AddReferenceToCollection(ByVal targetResource As Object, ByVal propertyName As String, _
                                     ByVal resourceToBeAdded As Object) _
                                     Implements IUpdatable.AddReferenceToCollection
            Dim pi = targetResource.GetType().GetProperty(propertyName)
            If pi Is Nothing Then
                Throw New Exception("Can't find property")
            End If
            Dim collection = CType(pi.GetValue(targetResource, Nothing), IList)
            collection.Add(resourceToBeAdded)
        End Sub
        ' Removes the object from the related objects collection.
        Sub RemoveReferenceFromCollection(ByVal targetResource As Object, ByVal propertyName As String, _
                                          ByVal resourceToBeRemoved As Object) _
                                          Implements IUpdatable.RemoveReferenceFromCollection
            Dim pi = targetResource.GetType().GetProperty(propertyName)
            If pi Is Nothing Then
                Throw New Exception("Can't find property")
            End If
            Dim collection = CType(pi.GetValue(targetResource, Nothing), IList)
            collection.Remove(resourceToBeRemoved)
        End Sub
            ' Deletes the resource.
        Sub DeleteResource(ByVal targetResource As Object) _
        Implements IUpdatable.DeleteResource
            Dim table = GetTable(targetResource.GetType())
            table.DeleteOnSubmit(targetResource)
        End Sub
        ' Saves all the pending changes.
        Sub SaveChanges() Implements IUpdatable.SaveChanges
            SubmitChanges()
        End Sub
        ' Returns the actual instance of the resource represented 
        ' by the resource object.
        Function ResolveResource(ByVal resource As Object) As Object Implements IUpdatable.ResolveResource
            Return resource
        End Function
            ' Reverts all the pending changes.
        Sub ClearChanges() Implements IUpdatable.ClearChanges
            ' Raise an exception as there is no real way to do this with LINQ to SQL.
            ' Comment out the following line if you'd prefer a silent failure
            Throw New NotSupportedException()
        End Sub
    End Class
    #End Region
    
    using System;
    using System.ComponentModel;
    using System.Collections;
    using System.Linq;
    using System.Reflection;
    using System.Data.Linq;
    using System.Data.Linq.Mapping;
    using System.Data.Services;
    using System.Data.Services.Common;
    
    namespace NorthwindService
    {
        // Define the key properties for the LINQ to SQL data classes.
        [DataServiceKeyAttribute("CustomerID")]
        public partial class Customer { }
    
        [DataServiceKeyAttribute("ProductID")]
        public partial class Product { }
    
        [DataServiceKeyAttribute("OrderID")]
        public partial class Order { }
    
        [DataServiceKeyAttribute("OrderID", "ProductID")]
        public partial class Order_Detail { }
    
        #region IUpdatable implementation
        // Define the IUpdatable implementation for LINQ to SQL.
        public partial class NorthwindDataContext : IUpdatable
        {
            // Creates an object in the container.
            object IUpdatable.CreateResource(string containerName, string fullTypeName)
            {
                Type t = Type.GetType(fullTypeName, true);
                ITable table = GetTable(t);
                object resource = Activator.CreateInstance(t);
                table.InsertOnSubmit(resource);
                return resource;
            }
    
            // Gets the object referenced by the resource.
            object IUpdatable.GetResource(IQueryable query, string fullTypeName)
            {
                object resource = query.Cast<object>().SingleOrDefault();
    
                // fullTypeName can be null for deletes
                if (fullTypeName != null && resource.GetType().FullName != fullTypeName)
                    throw new ApplicationException("Unexpected type for this resource.");
                return resource;
            }
    
    
            // Resets the value of the object to its default value.
            object IUpdatable.ResetResource(object resource)
            {
                Type t = resource.GetType();
                MetaTable table = Mapping.GetTable(t);
                object dummyResource = Activator.CreateInstance(t);
                foreach (var member in table.RowType.DataMembers)
                {
                    if (!member.IsPrimaryKey && !member.IsDeferred &&
                        !member.IsAssociation && !member.IsDbGenerated)
                    {
                        object defaultValue = member.MemberAccessor.GetBoxedValue(dummyResource);
                        member.MemberAccessor.SetBoxedValue(ref resource, defaultValue);
                    }
                }
                return resource;
            }
    
            // Sets the value of the given property on the object.
            void IUpdatable.SetValue(object targetResource, string propertyName, object propertyValue)
            {
                MetaTable table = Mapping.GetTable(targetResource.GetType());
                MetaDataMember member = table.RowType.DataMembers.Single(x => x.Name == propertyName);
                member.MemberAccessor.SetBoxedValue(ref targetResource, propertyValue);
            }
    
            // Gets the value of a property on an object.
            object IUpdatable.GetValue(object targetResource, string propertyName)
            {
                MetaTable table = Mapping.GetTable(targetResource.GetType());
                MetaDataMember member =
                    table.RowType.DataMembers.Single(x => x.Name == propertyName);
                return member.MemberAccessor.GetBoxedValue(targetResource);
            }
    
            // Sets the related object for a reference.
            void IUpdatable.SetReference(
                object targetResource, string propertyName, object propertyValue)
            {
                ((IUpdatable)this).SetValue(targetResource, propertyName, propertyValue);
            }
    
            // Adds the object to the related objects collection.
            void IUpdatable.AddReferenceToCollection(
                object targetResource, string propertyName, object resourceToBeAdded)
            {
                PropertyInfo pi = targetResource.GetType().GetProperty(propertyName);
                if (pi == null)
                    throw new Exception("Can't find property");
                IList collection = (IList)pi.GetValue(targetResource, null);
                collection.Add(resourceToBeAdded);
            }
    
            // Removes the object from the related objects collection.
            void IUpdatable.RemoveReferenceFromCollection(
                object targetResource, string propertyName, object resourceToBeRemoved)
            {
                PropertyInfo pi = targetResource.GetType().GetProperty(propertyName);
                if (pi == null)
                    throw new Exception("Can't find property");
                IList collection = (IList)pi.GetValue(targetResource, null);
                collection.Remove(resourceToBeRemoved);
            }
    
            // Deletes the resource.
            void IUpdatable.DeleteResource(object targetResource)
            {
                ITable table = GetTable(targetResource.GetType());
                table.DeleteOnSubmit(targetResource);
            }
    
            // Saves all the pending changes.
            void IUpdatable.SaveChanges()
            {
                SubmitChanges();
            }
    
            // Returns the actual instance of the resource represented 
            // by the resource object.
            object IUpdatable.ResolveResource(object resource)
            {
                return resource;
            }
    
            // Reverts all the pending changes.
            void IUpdatable.ClearChanges()
            {
                // Raise an exception as there is no real way to do this with LINQ to SQL.
                // Comment out the following line if you'd prefer a silent failure
                throw new NotSupportedException();
            }
        #endregion
        }
    }
    

Pour créer un service de données en utilisant un modèle de données LINQ to SQL

  1. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le nom de votre projet ASP.NET, puis cliquez sur Ajouter un nouvel élément.

  2. Dans cette boîte de dialogue Ajouter un nouvel élément, sélectionnez WCF Data Service.

  3. Fournissez un nom pour le service, puis cliquez sur OK.

    Visual Studio crée le balisage XML et des fichiers de code pour le nouveau service. La fenêtre de l'éditeur de code s'ouvre par défaut.

  4. Dans le code pour le service de données, remplacez le commentaire /* TODO: put your data source class name here */ dans la définition de la classe qui définit le service de données avec le type qui est le conteneur d'entités du modèle de données, dans ce cas NorthwindDataContext.

  5. Dans le code du service de données, remplacez le code d'espace réservé dans la fonction InitializeService par le code suivant :

    config.SetEntitySetAccessRule("Customers", EntitySetRights.ReadMultiple)
    config.SetEntitySetAccessRule("Orders", EntitySetRights.AllRead _
                                Or EntitySetRights.WriteMerge)
    config.SetEntitySetAccessRule("Order_Details", EntitySetRights.AllRead _
                                Or EntitySetRights.AllWrite)
    config.SetEntitySetAccessRule("Products", EntitySetRights.ReadMultiple)
    
    config.SetEntitySetAccessRule("Customers", EntitySetRights.ReadMultiple);
    config.SetEntitySetAccessRule("Orders", EntitySetRights.AllRead  
                                | EntitySetRights.WriteMerge);
    config.SetEntitySetAccessRule("Order_Details", EntitySetRights.AllRead                             
                                | EntitySetRights.AllWrite);
    config.SetEntitySetAccessRule("Products", EntitySetRights.ReadMultiple);
    

    Cela permet aux clients autorisés d'accéder aux ressources pour les trois jeux d'entités spécifiés.

  6. Pour tester le service de données Northwind.svc à l'aide d'un navigateur Web, suivez les instructions dans la rubrique Accès aux flux OData depuis un navigateur Web (démarrage rapide de WCF Data Services).

Voir aussi

Tâches

Procédure : créer un service de données à l'aide d'une source de données ADO.NET Entity Framework (WCF Data Services)

Procédure : créer un service de données à l'aide du fournisseur de réflexion (WCF Data Services)

Concepts

Fournisseurs de services de données (WCF Data Services)