WCF RIA Services and ComplexObjects

The release of the WCF RIA Services V1.0 SP1 Beta, added support for complex type members in entities and DomainService operations. Here is a quick walkthrough.

I started with Northwind database and customers table. I refactored some of the columns (Address,City,Region, PostalCode, Country) into a complex object called “AddressDetails” and updated the mappings like we see in the screenshot. Added a DomainService based on the model.

I added a Dataform in the Silverlight application like below

<toolkit:DataForm x:Name=”dataform1″ AutoEdit=”True” AutoCommit=”True”  
                          CommandButtonsVisibility=”All”  >
            <StackPanel>
                <toolkit:DataField Label=”CustomerId”>
                    <TextBox Text=”{Binding CustomerID, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”ContactName”>
                    <TextBox Text=”{Binding ContactName, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”ContactTitle”>
                    <TextBox Text=”{Binding ContactTitle, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”CompanyName”>
                    <TextBox Text=”{Binding CompanyName, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”Address”>
                    <TextBox Text=”{Binding AddressDetails.Address, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”City”>
                    <TextBox Text=”{Binding AddressDetails.City, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”PostalCode”>
                    <TextBox Text=”{Binding AddressDetails.PostalCode, Mode=TwoWay}”/>
                </toolkit:DataField>
                <toolkit:DataField Label=”Country”>
                    <TextBox Text=”{Binding AddressDetails.Country, Mode=TwoWay}”/>
                </toolkit:DataField>
            </StackPanel>   
        </toolkit:DataForm>
Here is the code behind.

public partial class MainPage : UserControl
    {
        DomainService1 ctx = new DomainService1();

        public MainPage()
        {
            InitializeComponent();

            this.DataContext = this;
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
            dataform1.EditEnded += new EventHandler<DataFormEditEndedEventArgs>(dataform1_EditEnded);
          
        }

        void dataform1_EditEnded(object sender, DataFormEditEndedEventArgs e)
        {           
            ctx.SubmitChanges();
        }
        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            LoadOperation<Customer> lo = ctx.Load<Customer>(ctx.GetCustomersQuery());
            lo.Completed += new EventHandler(lo_Completed);
        }

        void lo_Completed(object sender, EventArgs e)
        {
            dataform1.ItemsSource = (sender as LoadOperation<Customer>).Entities.ToList();
        }

    }

we can change data and click ok for the data to be saved. The Ok Button is not enabled, if the changes are made to the fields that are part of the complex object(“AddressDetails”). I tried to add a new customer. After filling in all the fields clicked “ok” button and got the error “AddressDetails is required”.  I added the following code to create a new instance of AddressDetails when a Customer is created
 public partial class Customer
    {
        partial void OnCreated()
        {
            this.AddressDetails = new AddressDetails();
          
        }             
    }

I did not get any error, but the new customer is not saved. The Context did not see any changes. so I had to explicitly add code to check the entitystate and add the object to the context for the new customer to be saved. I am not sure if I am missing something here.

 void dataform1_EditEnded(object sender, DataFormEditEndedEventArgs e)
        {
            if ((dataform1.CurrentItem as Customer).EntityState == EntityState.Detached)
                ctx.Customers.Add(dataform1.CurrentItem as Customer);
            ctx.SubmitChanges();
        }
We can also get the complex object by itself. I added the following code to get the AddressDetails for a given customer in the domainservice

  public AddressDetails GetCustomerAddressDetails(string customerId)
        {
            return this.ObjectContext.Customers.Where(x=>x.CustomerID == customerId).FirstOrDefault().AddressDetails;
        }

and call it like so from the client

ctx.GetCustomerAddressDetails(“ALFKI”, (io) => { AddressDetails details = io.Value; }, null);

The complexobject doesnt need to be based on an entity in the model, I added a customclass like below

    [Serializable()]
    [DataContract]
    public partial class CustomersSummary : ComplexObject
    {
        [Key]
        [DataMember]
        public string Country { get; set; }
        [DataMember]
        public int NumberOfCustomers { get; set; }
    }
wrote a method in the domainservice like below to return a list of the customobjects

  public IQueryable<CustomersSummary> GetCustomerSummary()
        {
            List<CustomersSummary> returnList=  this.ObjectContext.Customers.Where(c=>c.AddressDetails.Country !=null).GroupBy(x => x.AddressDetails.Country).Select(y => new CustomersSummary { Country = y.Key, NumberOfCustomers = y.Count() }).ToList();
            return returnList.AsQueryable();
        }

On the client the following code would get the list of customobjects.

ctx.Load<CustomersSummary>(ctx.GetCustomerSummaryQuery(), (lo) => { List<CustomersSummary> data = lo.Entities.ToList(); }, false);

Advertisements

One thought on “WCF RIA Services and ComplexObjects

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s