Export (0) Print
Expand All
2 out of 2 rated this helpful - Rate this topic

How to: Create a Data Service Using a LINQ to SQL Data Source (WCF Data Services)

WCF Data Services exposes entity data as a data service. The reflection provider enables you to define a data model that is based on any class that exposes members that return an IQueryable<T> implementation. To be able to make updates to data in the data source, these classes must also implement the IUpdatable interface. For more information, see Data Services Providers (WCF Data Services). This topic shows you how to create LINQ to SQL classes that access the Northwind sample database by using the reflection provider, as well as how to create the data service that is based on these data classes.

To add LINQ to SQL classes to a project

  1. From within a Visual Basic or C# application, on the Project menu, click Add New Item.

  2. Click the LINQ to SQL Classes template.

  3. Change the name to Northwind.dbml.

  4. Click Add.

    The Northwind.dbml file is added to the project and the Object Relational Designer (O/R Designer) opens.

  5. In Server/Database Explorer, under Northwind, expand Tables and drag the Customers table onto the Object Relational Designer (O/R Designer).

    A Customer entity class is created and appears on the design surface.

  6. Repeat step 6 for the Orders, Order_Details, and Products tables.

  7. Right-click the new .dbml file that represents the LINQ to SQL classes and click View Code.

    This creates a new code-behind page named Northwind.cs that contains a partial class definition for the class that inherits from the DataContext class, which in this case is NorthwindDataContext.

  8. Replace the contents of the Northwind.cs code file with the following code. This code implements the reflection provider by extending the DataContext and data classes generated by LINQ to SQL:

    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
        }
    }
    

To create a data service by using a LINQ to SQL-based data model

  1. In Solution Explorer, right-click the name of your ASP.NET project, and then click Add New Item.

  2. In the Add New Item dialog box, select WCF Data Service.

  3. Supply a name for the service, and then click OK.

    Visual Studio creates the XML markup and code files for the new service. By default, the code-editor window opens.

  4. In the code for the data service, replace the comment /* TODO: put your data source class name here */ in the definition of the class that defines the data service with the type that is the entity container of the data model, which in this case is NorthwindDataContext.

  5. In the code for the data service, replace the placeholder code in the InitializeService function with the following:

    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);
    

    This enables authorized clients to access resources for the three specified entity sets.

  6. To test the Northwind.svc data service by using a Web browser, follow the instructions in the topic Accessing the Service from a Web Browser (WCF Data Services Quickstart).

Show:
© 2014 Microsoft. All rights reserved.