WCF Ria Services Composition

Download VS2010 project:
WcfComposition.zip

Sometimes, MSDN gives buggy information. If you are using Composition, there are a number of calisthenics required to make this thing work.


namespace WcfComposition.Web
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Data;
    using System.Linq;
    using System.ServiceModel.DomainServices.EntityFramework;
    using System.ServiceModel.DomainServices.Hosting;
    using System.ServiceModel.DomainServices.Server;
    using System.Data.Objects.DataClasses;
    using System.Data.Objects;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.ServiceModel.DomainServices;

    // Implements application logic using the CompositionEntities context.
    // TODO: Add your application logic to these methods or in additional methods.
    // TODO: Wire up authentication (Windows/ASP.NET Forms) and uncomment the following to disable anonymous access
    // Also consider adding roles to restrict access as appropriate.
    // [RequiresAuthentication]
    [EnableClientAccess()]
    public class OrdersService : LinqToEntitiesDomainService<CompositionEntities>
    {

        public IQueryable<CustomerOrder> GetCustomerOrders()
        {
            return this.ObjectContext.CustomerOrders.Include("OrderDetails");
        }

        public void InsertCustomerOrder(CustomerOrder customerOrder)
        {
            if ((customerOrder.EntityState != EntityState.Detached))
            {
                this.ObjectContext.ObjectStateManager.ChangeObjectState(customerOrder, EntityState.Added);
            }
            else
            {
                this.ObjectContext.CustomerOrders.AddObject(customerOrder);
            }

            UpdateAssociatedDetails(customerOrder);
        }

        private void UpdateAssociatedDetails(CustomerOrder customerOrder)
        {
            System.Collections.IEnumerable details =
                this.ChangeSet.GetAssociatedChanges<CustomerOrder, EntityCollection<OrderDetail>>
                    (customerOrder, o => o.OrderDetails);
            foreach (OrderDetail detail in details)
            {
                ChangeOperation op = this.ChangeSet.GetChangeOperation(detail);
                switch (op)
                {
                    case ChangeOperation.Insert:
                        if (detail.EntityState != EntityState.Added)
                        {
                            if (detail.EntityState != EntityState.Detached)
                            {
                                this.ObjectContext.ObjectStateManager.ChangeObjectState(detail, EntityState.Added);
                            }
                            else
                            {
                                this.ObjectContext.OrderDetails.AddObject(detail);
                            }
                        }
                        break;

                    case ChangeOperation.Update:
                        if (detail.EntityState == EntityState.Detached)
                        {
                            this.ObjectContext.Attach(detail);
                        }
                        this.ObjectContext.ObjectStateManager.ChangeObjectState(detail, EntityState.Modified);
                        break;

                    case ChangeOperation.Delete:
                        if (detail.EntityState == EntityState.Detached)
                        {
                            this.ObjectContext.OrderDetails.Attach(detail);
                        }
                        customerOrder.OrderDetails.Remove(detail);
                        this.ObjectContext.DeleteObject(detail);
                        break;

                    case ChangeOperation.None:

                        // MSDN had omitted these
                        if (detail.EntityState == EntityState.Added)
                            this.ObjectContext.ObjectStateManager.ChangeObjectState(detail, EntityState.Unchanged);
                        break;

                    default:
                        break;
                }

            }

            double totalPrice = customerOrder.OrderDetails.Sum(d => d.Price);
            customerOrder.TotalPrice = (float) totalPrice;
        }

        public void UpdateCustomerOrder(CustomerOrder currentCustomerOrder)
        {
            try
            {
                if (currentCustomerOrder.EntityState == EntityState.Detached)
                {

                    CustomerOrder originalOrder = this.ChangeSet.GetOriginal(currentCustomerOrder);
                    if (originalOrder != null)
                    {
                        this.ObjectContext.CustomerOrders.AttachAsModified(currentCustomerOrder, originalOrder);

                    }
                    else
                    {
                        // http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/a633a58e-85ad-4e77-be80-b1855bfd2b42
                        this.ObjectContext.CustomerOrders.AddObject(currentCustomerOrder);
                        this.ObjectContext.ObjectStateManager.ChangeObjectState(currentCustomerOrder, EntityState.Unchanged);

                        // MSDN is wrong.
                        // this.ObjectContext.CustomerOrders.Attach(currentCustomerOrder);
                    }
                }

                UpdateAssociatedDetails(currentCustomerOrder);
            }
            catch (Exception exc)
            {
                string message = exc.Message;
                throw;
            }

        }

        public void DeleteCustomerOrder(CustomerOrder customerOrder)
        {
            if ((customerOrder.EntityState == EntityState.Detached))
            {
                this.ObjectContext.CustomerOrders.Attach(customerOrder);
            }
            foreach (var detail in customerOrder.OrderDetails.ToList())
                this.ObjectContext.DeleteObject(detail);
            this.ObjectContext.CustomerOrders.DeleteObject(customerOrder);
        }

    }

}

Formatting courtesy of Code to HTML format


About this entry