# Monday, 28 June 2010

A few months ago I wrote to you about why teams succeed. I talked about the “high bandwidth” team that stressed communication and collaboration. While I believe that communication and collaboration are the keys to success of any team, I always felt that there was another important component to the equation.

I visited a large retail global customer here in Hong Kong today. They are working on a large application for their product development group using Silverlight 4.0 and have teams in the United States, India, and Hong Kong. We were talking first about their use of Telerik tools and then the conversation moved on to teams and process. They are having success and are using the agile methodology Kanban. When I left, they were proud to show me their Kanban board with all of their user stories, tasks, features, and burn down.

clip_image001

That is when it hit me; the other component of highly successful teams is transparency. I started looking back throughout my career and looked at the high performing teams that had successful projects and the very successful ones were the ones that had the magic combination of high bandwidth and transparency.

I remember ten years ago building the original Zagat.com at the height of the .COM boom. We held “open staff meetings” where our weekly staff meetings were attended by other managers from around the company. Our own version of a Kanban board was posted outside the door of our main room. We were still using Microsoft Project and Gantt charts, each chart for each project was hanging outside of the room as well and updated daily. That level of transparency built trust with the organization and enabled us to work with the business closer.

I use to get pushback from the team about our transparency; the team did not like transparency when they were behind schedule. My argument was that we had to show the good, the bad, and the ugly. Besides, it is a well-known fact that we are motivated to work hard not by money, but by our creativity and the chance to produce something truly awesome. I figured that if we make that process more public and transparent, the employees would be even more motivated. By making our product development cycle public, the team took more pride in what they did since everyone was watching.

In addition, this process solved minor disputes between team members. Once when the VP of Marketing was at our open staff meeting, two developers were arguing over something petty. They forgot that the VP of marketing was there and later told me that they “looked bad” in front of the marketing VP. The next time I made sure that the founder of the company was at our staff meeting. Everyone on the team got the message and the transparency worked.

I was also very transparent with the business information coming into IT. I use to disseminate our monthly sales numbers (which were a closely guarded secret) to the whole department. The CEO asked me to stop since IT were the only people in the company besides the senior management to know this information. I responded with even more transparency and shared with the team our profit and loss information as well. (The CEO was not happy, but to her credit, she did not stop me.)

The Agile movement really helped push the importance of transparency forward. The very intention of the Scrum or Kanban board is to be public; same with the daily scrum meeting. If the business is engaged and attending your meetings, there is going to be more productivity and much less friction. Luminary Kent Beck wrote a white paper on agile tooling and teams where he stressed transparency. Beck says:

“When I started programming the weekly status report was sufficient. Here’s what I did this week, here’s what I’m planning to do next week. Press fast forward twice, though, and the weekly status report becomes as quaint as a debate about the relative merits of assembly language and higher level languages. … transparency is a choice you make to offer trustworthiness to you teammates. A transparent team can more cheaply and effectively coordinate their efforts towards shared goals. Acting transparently sends a signal to others that they can trust you. Trust, when realized, reduces the friction of development as people focus more on what they are accomplishing together and less on avoiding blame.”

Ten years after my experiences at Zagat, it is even easier to be transparent. There are many tools that help with transparency. Kent Beck also states in the white paper:

“One way out of the Reporting Dilemma is to stop explicitly telling people what you are doing. Instead, rely on your tools to infer your intentions from your activities and report that for you.”

Agile teams usually publish burn down charts and team velocity charts to report progress between iterations. In an effort to be both more transparent and more automated, the industry has moved to Agile Dashboards, dashboards that read from your repository and automatically publish your burn down and velocity charts as well as other vital information related to the iteration and build process (including my personal favorite, who broke the build.)

Several vendors offer an agile dashboard, such as i.e. Rally’s Team Status Dashboard, VersionOne, and of course Telerik. Our Agile Dashboard, a free tool, posts all the important details of a project on a dashboard for the whole world to see. This tool is meant to be on a large TV, hanging over the receptionist’s desk when you walk into a company complete the status of the current iteration, burn down charts, and even a photo of who last broke the build.

clip_image002

This decade will be remembered as the era when technology teams fully embraced transparency. As teams start to automate their transparency and look for ways to be more open, the quality of the software they produce will only improve. I look forward to this brave new (open) world.

posted on Monday, 28 June 2010 01:44:44 (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback
# Friday, 25 June 2010

The battle for mobile supremacy has really heated up. Apple and Goolge had round 1 back in January with the release of the Google Nexus One. With the release of the iPhone 4 and the Droid X we are well into round 2.  I am not going to debate which device is better or worse, that is for the market to shake out. Rather I want to comment on how the popularity of each device is strengthening its underlying platform. The iPhone 4.0 and iPad 1.0 run on iOS 4. Google’s mainline devices run Android 2.1 or will be upgraded to Android 2.2. “Froyo'”.  It has been reported that Google will release an iPad style “Google Pad” based on Android 2.x as well. Developers are lining up to write applications for these two platforms, each expanding from the phone to a slate/tablet device. It is possible you may see netbook style devices running iOS and Android soon. That said, looking ahead 5 years from now, which one will “win” the most mindshare?

Apple’s iOS is quite popular since the iPhone and iPad are selling so well. Developers are turned off by the AppStore’s approval process and Objective-C in general. Apple also maintains complete control over iOS and you can’t license it and put it on your own consumer electronics device. Android is more open and easier to program for since it uses the more mainstream Java language. It is also possible that you can use Android on other devices (I know a company here in Hong Kong building a consumer electronics device based on Android.) Also, Google’s marketplace is not restricted (hence you can download porn apps if you like.)

In the long term my money is behind Google for two reasons: it is easier to code for and it more open. Eventually what you will see is applications appearing first on the Android then on the iPhone, with some never making it over for AppStore reasons or for Objective-C reasons. (This already happened with several World Cup focused applications.) Applications are what make a platform, you can have a more “cool” platform with less apps and the less “cool” platform with more apps will still win. Think Mac v PC 15+ years ago.

Speaking of PCs, where is Microsoft in all of this? The Zune based Windows Phone 7 is not slated to come out any time soon. By the time WP7 ships we will be talking about iPhone 5.0 rumors, Android 3.0 rumors, and the next generation iPad. Microsoft has a lot of catching up to do.

posted on Friday, 25 June 2010 05:40:43 (Eastern Daylight Time, UTC-04:00)  #    Comments [2] Trackback
# Thursday, 24 June 2010

Read the other posts in this series:

In the previous blog posts listed above, I showed how Telerik’s new LINQ implementation works with WCF RIA Services. I showed how to build your own Domain Service, build custom query methods, and make a metadata class. In this post I will show how to expose your Domain Service as an OData feed.

The Open Data Protocol (OData) is a Web protocol for querying and updating data in a RESTful fashion. You create OData feeds when you want to set up feeds for 3rd parties to consume, typically without your knowledge. For example Twitter has a RESTful feed of all its public tweets and many applications will consume that feed.

You may use WCF RIA Services to create your application, however, you may want to expose parts of your application as a feed for others to consume. This is real easy to do. Let’s see how.

I will continue using the same project from the first three parts of this blog series. In the server (ASP.net) project you have to do three things. First set a reference to System.ServiceModel.DomainServices.Hosting.OData.

Next we have to configure an OData endpoint. You do this by adding the following to your web.config under the system.serviceModel node:

<domainServices>
  <endpoints>
   <add 
name="OData" type="System.ServiceModel.DomainServices.Hosting.ODataEndpointFactory, 
System.ServiceModel.DomainServices.Hosting.OData, 
Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
  </endpoints>
</domainServices>

Lastly, you have to tell RIA Services what methods of your DomainService you want to expose. The methods you expose have to be an IQueryable and parameterless (which means the query methods in Part II are ineligible) and decorated with the IsDefult=true attribute. I will expose our GetCustomers() method from Part I as shown here by adding the attribute to the method:

   1:  //enable OData
   2:  [Query(IsDefault = true)]
   3:  public IQueryable<Customer> GetCustomers()
   4:  {
   5:      return this.DataContext.Customers
   6:          .Where(c => c.Country == "Germany")
   7:          .OrderBy(c => c.CustomerID);
   8:  }

Now you can run your project and view the OData feed from a browser. The format of the URL is the namespace+typename for the DomainService with dots replaced by hyphens followed by “.svc/odata/”. (Note, I have found that this is case sensitive and requires the terminating /.)

So for example, our Namespace is SilverlightApplication6.Web and our Domain Service is DomainService1, so our url would be http://servername/SilverlightApplication6-Web-DomainService1.svc/odata/

My URL is the following and the results are shown below:

http://localhost:1055/SilverlightApplication6-Web-DomainService1.svc/odata/

clip_image002

Now let’s explore the OData feed. Being a RESTful service you will access the feed and each resource via HTTP. The resource in this case will be the names of your Entities. What is great is that the OData feed respects the business rules of your RIA Service (since it is using the same DomainService), so you don’t have to worry about data leakage, nor duplicate any work replicating your business rules. Let’s drill down into the CustomerSet:

http://localhost:1055/SilverlightApplication6-Web-DomainService1.svc/odata/CustomerSet

clip_image004

That is it. You can then consume the feed from an iPhone app, .NET application, Excel PowerPivot, or any other application that supports HTTP and XML (which is pretty much anything.)

Enjoy!

posted on Thursday, 24 June 2010 04:00:03 (Eastern Daylight Time, UTC-04:00)  #    Comments [2] Trackback
# Wednesday, 23 June 2010

Even though I played soccer as a kid, I grew up watching mostly professional baseball. Even though I did catch Pele play a few matches for the NY Cosmos as a kid, my love for professional soccer started when the US hosted the 1994 World Cup. My professional speaking career, however, seems to be linked to professional soccer.

It all started at my very first TechEd: TechEd Europe 1998 in Nice, France. Prior to 2006, TechEd Europe was held in early summer, always causing me to spend the July 4th independence day outside of the United States. Back in 1998, France was hosting the World Cup and subsequently won it all. While I got caught up in all of the hoopla, I also had to speak at an event in London the next week and the entire country of France shut down, making it impossible for me to travel. Thus began the link with my professional speaking and soccer.

As the years went by I found myself speaking in Barcelona six times and went to FC Barcelona matches each year and they became my favorite team. in 2005 I found myself in Turkey when the European Cup was going on (and had to deal with the traffic since the speaking venue was right near the stadium). In 2006 I found myself in Egypt during the Africa Cup and was in a taxi trying to get to my speaking event in standstill traffic as the entire city tried to obtain tickets for the final match. I had to get out of the taxi and run 3km to the venue to make my talk in time. (I called Patrick Hynds to stall the crowd, but did make it with 5 minutes to spare.) I watched Egypt win the finals on penalty kicks a few days later in the middle of the street in Luxor with about 20 locals surrounding a tiny black and white TV while Kathleen shopped. We all smoked shisha together to celebrate and the shop owner (who was ignoring Kathleen and watching the game) gave us an additional 50% discount on all sales. After Kathleen finished buying her stuff, all of us, including Goksin’s 7 year old daughter, started running through the streets to celebrate.

One of the most memorable experiences was also in Egypt. in 2004 FIFA stated that Egypt, Morocco, and South Africa were the favorites to host the 2010 World Cup. I was in Egypt and Morocco during that time and met up with several MVPs for dinner. They all asked me: “Do you support an African World Cup?” I said yes and said that I will travel back to Africa to watch the world cup in 2010.

This weekend I kept my promise. I had a nice long weekend in South Africa and went to a few matches, keeping my promise to the African MVPs. (You can even look closely at this photo, besides my Team USA jersey, I am wearing my 2010 MVP jacket, and boy did I need it, it was coooold!)

Most of the non-African world hates the vuvuzela horn. The vuvuzela is an uniquely African (mostly South African) cultural experience. You can’t enjoy soccer in southern Africa without it. Showing my support for the African World Cup, I went native and blew that horn all night long.

IMG_1721

I am glad that I was able to keep my 6 year old promise. It seems that professional soccer and my speaking career are linked. Any Brazilian MVPs/RDs want to put me up in 2014?

posted on Wednesday, 23 June 2010 02:21:51 (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback
# Tuesday, 22 June 2010

Tuesday, June 29, 2010
Parallel Programming with .NET 4 and Visual Studio 2010

Subject:
You must register athttp://parallelcomputingtalk.eventbrite.com/ in order to be admitted to the building and attend.

In the past, introducing concurrency and parallelism into libraries and applications was difficult, time consuming, and error-prone. However, as the hardware industry shifts towards multi-core and manycore processors, the key to high-performance applications is parallelism. The .NET Framework 4 and Visual Studio 2010 offer solutions to help make coding, debugging, and profiling concurrent applications significantly easier. In this interactive deep-dive, we’ll examine Parallel LINQ-to-Objects (PLINQ), the Task Parallel Library (TPL), new coordination and synchronization types, and Visual Studio tooling support in order to provide a look at the next generation of parallel programming with .NET.

Speaker:
Stephen Toub, Microsoft
Stephen Toub is a Principal Program Manager on the Parallel Computing Platform team at Microsoft. He’s excited to be back in Manhattan, where he lived and worked for several years.

Date:
Tuesday, June 29, 2010

Time:
Reception 6:00 PM , Program 6:15 PM

Location: 
Microsoft , 1290 Avenue of the Americas (the AXA building - bet. 51st/52nd Sts.) , 6th floor

Directions:
B/D/F/V to 47th-50th Sts./Rockefeller Ctr
1 to 50th St./Bway
N/R/W to 49th St./7th Ave.

posted on Tuesday, 22 June 2010 04:48:59 (Eastern Daylight Time, UTC-04:00)  #    Comments [1] Trackback
# Monday, 21 June 2010

Read the other posts in this series:

In the previous blog posts listed above, I showed how Telerik’s new LINQ implementation works with WCF RIA Services. I showed how to build your own Domain Service as well as build custom query methods. In this post I will show how to build a metadata class. (Note: future versions of the OpenAccess LINQ Implementation will produce the metadata class for you automatically.)

The WCF RIA Services metadata class is a separate class from the DomainService that contains information about the entities. In this class you can write custom validation logic, set attributes of the properties of the entities or indicate whether the property is to be generated on the client or not.

To create this class, create a new class in Visual Studio and name it: YourDomainSeriveClassName.metadata.cs. For example, our DomainService is DomainService1, so the metadata class is: DomainService1.metadata.cs.

Erase everything in the class and then replace it with the following, using the proper namespace in your project:

 

   1:  namespace SilverlightApplication6.Web
   2:  {
   3:      using System.ComponentModel.DataAnnotations;
   4:   
   5:      // The MetadataTypeAttribute identifies CustomersMetadata as the class
   6:      // that carries additional metadata for the Customers class.
   7:      [MetadataTypeAttribute(typeof(Customers.CustomersMetadata))]
   8:      public partial class Customers
   9:      {
  10:          internal sealed class CustomersMetadata
  11:          {
  12:              // Metadata classes are not meant to be instantiated.
  13:              private CustomersMetadata()
  14:              {
  15:              }
  16:              public string Address { get; set; }
  17:              public string City { get; set; }
  18:              public string CompanyName { get; set; }
  19:              public string ContactName { get; set; }
  20:              public string ContactTitle { get; set; }
  21:              public string Country { get; set; }
  22:              public string CustomerID { get; set; }
  23:              public string Fax { get; set; }
  24:              public string Phone { get; set; }
  25:              public string PostalCode { get; set; }
  26:              public string Region { get; set; }
  27:          }
  28:      }
  29:  }

As you can see this class has each of the properties of your entity (lines 16-26), now you can set them as required, specify a length, or validate with a RegEx pattern. You can also specify that a property should not be sent down to the client. Of course you can specify much more sophisticated rules, you can even write your own methods.

Let’s do a quick example on the CompanyName property, we will set it to required, set an error message to be displayed if the field is not entered as well as set a length of 32. This is done with two attributes:

   1:  [Required(ErrorMessage = "CompanyName is Required!!")]
   2:  [StringLength(32)]
   3:  public string CompanyName { get; set; }

Now when you perform databinding, RIA Services will enforce these rules for you on the client. For example, if try to edit our data in the application built in Part II, RIA Services automatically adds validation for us and passes on the error message we specified in the attribute. (Note you have to add an UpdateCustomer method to your DomainService1 class to enable editing.)

clip_image002

Enjoy!

posted on Monday, 21 June 2010 06:55:05 (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback
# Friday, 18 June 2010

In my last blog post, I showed how Telerik’s new LINQ implementation works with WCF RIA Services. In that post I built a Domain Model from the Northwind database as well as a RIA Services Domain Service. I then showed the drag and drop features of RIA Services and created a simple Silverlight application with no code. Today we are going to take that example one step further by creating some custom server side Query Methods.

A query method is just a facility to query a data source. In RIA Services, you define a query method explicitly so it can be used on the client. This is pretty straight forward with RIA Services. Let’s create a query method to query the Customer table by its primary key (CustomerID) in the database. To do this, open the project we used in the previous blog post and add this code to the DomainService class in the server project.

   1:      //This query method will return only 1 customer
   2:      [Query(IsComposable = false)]
   3:      public Customer GetCustomersByID(string customerID)
   4:      {
   5:          //must also include the Germany restriction
   6:          //to keep in sync with the GetCustomers business logic
   7:          return this.DataContext.Customers.SingleOrDefault
   8:              (c => c.CustomerID == customerID 
   9:                  && c.Country=="Germany");
  10:      }

 

This method will return one customer and you need to specify that by the attribute IsComposable=False (Line 2). Everything else is pretty basic, you have a method signature that accepts a parameter (Line 3) and a LINQ statement that filters the data by CustomerID as well as by country (lines 8-9). We are filtering by country as well because in our original business logic (in Part I) we had a GetCustomers() method that filtered all of the records by the country Germany. This new GetCustomersByID method knows nothing of the GetCustomers() method so we have to replicate that business logic here. (We have hard coded the value of Germany, in a production application, you would most likely obtain this value from a database or cookie after authentication.)

Let’s create a second query method, one that will filter the Customer data source by the ContactName field and return a collection, not a single item. We define an IQueryable collection of Customer as the return value in the method signature (Line 3) and accept a parameter. This parameter is used in our LINQ statement to filter the data source (Lines 9-10). In addition, just like the previous example, we must also filter by the country Germany; also replicate the OrderBy of our GetCustomers() method (Line 11).

   1:  //This query method will return a collection of customers
   2:  //filtered by the letters passed in on the contact name
   3:  public IQueryable<Customer> GetCustomersByLetter(string letter)
   4:  {
   5:      //must also include the Germany restriction
   6:      //to keep in sync with the GetCustomers business logic
   7:      //also since we are returning a collection, must
   8:      //respect the OrderBy as well from the business logic
   9:      return this.DataContext.Customers.Where
  10:          (c => c.ContactName.StartsWith(letter) == true
  11:              && c.Country == "Germany").OrderBy(c => c.CustomerID);
  12:  }

 

Now that we have defined two query methods, let’s wire them up to our XAML form in the Silverlight application.

In our Silverlight application, delete the grid that we had dragged onto the form in Part I. Replace it with two labels, two text boxes, two buttons and a grid (set the grid’s AutoGenerateColumns property to True.) Your XAML page should look something like this:

image

Now we have to write some code.

In the last blog post we were able to use the drag and drop features of RIA Services and not write any code. Today I will show you how to perform similar and more advanced functions with just a little bit of code. First we need two using statements in order to get working:

using SilverlightApplication6.Web;
using System.ServiceModel.DomainServices.Client;

Next we need to create a global variable for the RIA Services DomainService’s context.

   1:  //domain context for all RIA operations
   2:  private DomainService1 domainContext = new DomainService1();

 

Next we will load the grid with all of the data the first time the XAML form loads. We load the data by calling the GetCustomers() method we created in the previous blog post (we use the domainContext global variable in line 6.).

   1:  void MainPage_Loaded(object sender, RoutedEventArgs e)
   2:  {
   3:      //since we are going across the wire, must explicitly tell
   4:      //RIA Services that we are going to load data 
   5:      LoadOperation<Customer> loadOperation = 
   6:          domainContext.Load<Customer>(domainContext.GetCustomersQuery());
   7:      //the actual binding of the results, RIA takes care of the async
   8:      this.dataGrid1.ItemsSource = loadOperation.Entities;
   9:  }

 

This code does the same thing as the drag and drop did in the previous blog post, call GetCustomers() (Lines 5-6) and bind the results (line 8). Notice in the codegen on the client, RIA Services appends the word “Query” to all query methods.  In the previous blog post this was done automatically, but today we did it via code. If we run this it will give us the following view:

image

Now let’s wire up the buttons so we can perform the filters. First we will wire up the button that will search by CustomerID. That button click event will call the GetCustomerByID query method (lines 11-13) and bind the results (line 15.) We have to pass in the data the user entered in the text box, make sure in production to validate this data!

   1:  private void button1_Click(object sender, RoutedEventArgs e)
   2:  {
   3:      //disable the buttons during the async load
   4:      //to prevent the user from clicking twice while waiting
   5:      button1.IsEnabled = false;
   6:      button2.IsEnabled = false;
   7:   
   8:      //since we are going across the wire, must explicitly tell
   9:      //RIA Services that we are going to load data 
  10:      //Also here is where you pass the parameter in 
  11:      LoadOperation<Customer> loadOp = domainContext.Load
  12:          (domainContext.GetCustomersByIDQuery(textBox1.Text), 
  13:              CustomerLoadedCallback, null);
  14:      //the actual data binding, RIA takes care of the async
  15:      dataGrid1.ItemsSource = loadOp.Entities;
  16:  }

As part of the operation, RIA Services will handle the asynchronous processing for you. The problem is that users are not used to async operations, so they may try to click on the button more than once. We account for this by disabling the buttons (lines 5-6) until the operation is complete.  We have to catch the end of the async operation in a callback function and pass that in as a parameter to the operation (line 13). The callback function is here:

   1:  //callback function for when the load is complete
   2:  private void CustomerLoadedCallback(LoadOperation<Customer> loadOperation)
   3:  {
   4:      //re-enable our buttons
   5:      //if you want to display an "IsBusy" graphic
   6:      //this is where you would remove it
   7:      button1.IsEnabled = true;
   8:      button2.IsEnabled = true;
   9:  }

 

Let’s run this and test it out. If you filter by “ALFKI”, the results look like this:

image

Now let’s do the same for the the filter by ContactName. The code behind the button event is here:

   1:  private void button2_Click(object sender, RoutedEventArgs e)
   2:  {
   3:      //disable the buttons during the async load
   4:      //to prevent the user from clicking twice while waiting
   5:      button1.IsEnabled = false;
   6:      button2.IsEnabled = false;
   7:   
   8:      //since we are going across the wire, must explicitly tell
   9:      //RIA Services that we are going to load data 
  10:      //Also here is where you pass the parameter in 
  11:      LoadOperation<Customer> loadOp = domainContext.Load
  12:          (domainContext.GetCustomersByLetterQuery(textBox2.Text),
  13:              CustomerLoadedCallback, null);
  14:      //the actual data binding, RIA takes care of the async
  15:      dataGrid1.ItemsSource = loadOp.Entities;
  16:  }

Similar to the previous example, we are calling the query method, this time GetCustomersByLetter (lines 11-13) and passing in the value the user typed into the text box. When we run this and filter by all contacts that start with the letter H, it looks like this:

image

Hopefully with these two examples you can see the power of using Telerik’s new LINQ implementation and WCF RIA Services.

Enjoy!

posted on Friday, 18 June 2010 05:20:56 (Eastern Daylight Time, UTC-04:00)  #    Comments [0] Trackback
# Thursday, 17 June 2010

With the Q1 release of Telerik OpenAccess ORM, Telerik released a brand new LINQ Implementation and supporting Visual Entity Designer. With the upcoming Q2 release next month, we will introduce full WCF RIA Services support. If you want to get started now you can wire up the services yourself pretty easily. Let’s take a look at how to get your feet wet with RIA Services and Telerik’s LINQ implementation.

Before you get started, you will need a few things installed:

  • Visual Studio 2010
  • Silverlight 4
  • WCF RIA Services for Visual Studio 2010
  • Northwind sample database
  • Telerik OpenAccess ORM Q1 Service Pack 1 or higher

Getting Started: The Easy Stuff

Let’s create a new Silverlight application first. In the New Silverlight Application dialog, check the “Enable WCF RIA Services” checkbox. This will enable RIA Services.

image

The next step is to create a new Telerik Domain Model in the server (ASP.NET) project. I have a detailed walk through here on how to do that. We’ll create a new Domain Model by right clicking on the server project and selecting “Add” and choosing the Telerik Domain Model from the menu. Then we will map all of the tables from Northwind using the wizard. We’ll also keep the default model name of NorthwindEntityDiagrams.

image

We’re in good shape. So far if you have used the new LINQ Implementation nothing is new (or LINQ to SQL/EF for that matter.)  Now let’s add the RIA Services stuff.

Housekeeping-Adding References

Since our RIA Services support is still beta, you have to wire up a few things manually, including some references. You need to add:

  • Telerik.OpenAccess.Ria.Extensions.dll (found under “Browse: Program Files|Telerik|OpenAccess ORM|Bin)
  • System.ServiceModel.DomainServices.Server.dll
  • System.ServiceModel.DomainServices.Hosting.dll
  • System.ComponentModel.DataAnnotations.dll

image

Now we are ready to create the domain class.

Creating the Domain Class

Add a new Domain Service Class by right clicking and selecting Add|New Item and choose Domain Service Class.

image

Accept the defaults in the dialog and then we are ready to go. (Note at this time OpenAccess does not support creation of the class for metadata, but will soon, possibly even before Q2.)

image

Once you accept this dialog, a new empty class is generated.

   1:      [EnableClientAccess()]
   2:      public class DomainService1 : DomainService
   3:      {
   4:      }

 

We need to add a using statement so we can make sure our DomainService uses the OpenAccess model: using Telerik.OpenAccess;

Now change the inheritance of DomainService1 to this:

   1:  [EnableClientAccess()]
   2:  public class DomainService1 : OpenAccessDomainService<NorthwindEntityDiagrams>
   3:  {
   4:  }

Now we have one last step to create our DomainService, we have to add the CRUD methods. (In the future all of this will be done automatically for you!)

   1:  {
   2:      public IQueryable<Customer> GetCustomers() 
   3:      { 
   4:          return this.DataContext.Customers; 
   5:      }
   6:   
   7:      public void InsertCustomer(Customer c)
   8:      {
   9:          this.DataContext.Add(c);
  10:          this.DataContext.SaveChanges();
  11:      }
  12:      public void DeleteCustomer(Customer c)
  13:      {
  14:          this.DataContext.Delete(c);
  15:          this.DataContext.SaveChanges();
  16:      }

These are the methods of your DomainService. You can also add business logic here. Let’s do that with our GetCustomers() query.  I will write some business logic that filters all of the customers by the country of Germany. Of course you would have more complex business logic here, however, I just want to demonstrate the point. All clients that use this DomainService will inherit this business logic, even if you expose your service as an OData feed. Our implementation is here:

   1:  public IQueryable<Customer> GetCustomers() 
   2:  { 
   3:      return this.DataContext.Customers
   4:          .Where(c=> c.Country=="Germany")
   5:          .OrderBy(c=> c.CustomerID); 
   6:  }

 

Now you are done. Compile and let’s get cracking on a Silverlight client.

Creating the Silverlight Client

This is the easy part. We’ll use the RIA Services drag and drop features. Open MainPage.XAML in the Silverlight application and in the Data Sources window, drag and drop the Customer entity to the XAML form. (Tip: if the Data Sources window is blank or not showing up, you can manually force it to come up via the “Data” menu option on the main menu in Visual Studio.)

Once you drag and drop the entity to the form, a grid will automatically show up.

image

Now press F5 and see the application running.

image

That's it! We just created an OpenAccess based RIA Services application!

Of course there is a lot more to RIA Services than just binding a grid, however, this demonstration should show you that once you create your DomainService class, all of the RIA Services “stuff” just works for you. In future posts we will look at more RIA Services features as well as creating a query method.

Enjoy!

posted on Thursday, 17 June 2010 09:06:30 (Eastern Daylight Time, UTC-04:00)  #    Comments [3] Trackback