Beth's Chinese blog
My favorite holiday is Halloween and I'm throwing a huge party at my super-freaky haunted house. I've got the whole place decorated -- which was a challenge to get done on time because I attended PDC. I drove back yesterday afternoon and I decorated until midnight. Now it's time to go outside and build the haunted tunnel through the garage. I've got about 2 hours of makeup so I hope I can get this all built in time! I'll take pictures and post them like I did last year.
Even my cat Zoe is dressing up this year, she's a black cat and I got her a cool cape. She's already started practicing scarring people.
Enjoy and be safe tonight!
Day 3 at PDC is off to a great start so far. I just attended a session on the architecture and development of the content delivery infrastructure and Silverlight client for the NBC Olympics online. It's pretty amazing how they pulled it off but one of the reasons for the success was scrumming and face-to-face meetings. With teams scattered all over the globe from Redmond to Beijing it takes great project management besides super technical skills to drive success. This is key to any software project, not just large ones like this.
DATA EVERYWHERE
Now I'm sitting in a session with Pablo Castro, a Software Architect over in SQL, on offline-enabled data services and desktop applications. This one is really good. I'm really interested in this one because on my former system that I developed we implemented our own data caching mechanisms and some of the challenges once you decide what data can be offline is how to efficiently synchronize it with the server as well as determining how stale you can tolerate the data. The plumbing for serializing and syncing the data is non-trivial so I'm happy to see these frameworks that handle that for you.
ADO.NET Data Services (Astoria) make it really really easy for you to put your data on the web. I've been getting into it since it was added to Visual Studio 2008 SP1. I think that combining this with Sync Services will make a great framework for you to build an easy data caching framework as well as enable you to "play back" calls to the service for you once you get back online. Pablo referred to this as "Astoria Offline" integrated into Visual Studio. I can't wait.
He built a simple ADO.NET Data Service (just like Saaid showed here) using the Entity Framework to model some data. The service then exposes this model to the web. The new thing he showed is that when creating the service there was an option on the dialog to create an offline enabled service. This adds code to enable sync services and scripts to modify the SQL Server database schema to enable change tracking on the tables (similar to how you do it now in VS 2008 using sync services, like Milind showed here). Then Pablo added a WPF client. and added a Service Reference to the data service. Because it was set up as an offline-enabled service it asks you if you want to take the service offline. If you say yes then it downloads the metadata from the service, creates a local SQL CE database and then adds an Entity Framework model to the local database. This allows you to code against the local data model which then syncs with the service behind the scenes using an orchestrator. VERY COOL. Its amazing what you can do with Visual Studio.
DOWNLOADS
Speaking of Visual Studio --- Visual Studio 2010 and .NET 4.0 CTP was released on Monday so have a look at an early build of the next version of VS. I'll be bugging the Visual Studio teams for Channel 9 videos in the coming months to show us what they got in there and how to use it. Now's the time for feedback so play with it and tell us about it on the Dev10 CTP Feedback page and the feedback forums.
Other things to look at and play with:
Windows Azure Tools for Microsoft Visual Studio CTP
Channel 9 PDC news and announcements
PDC Online
Enjoy!
What a busy week! Every time I sat down to write this blog post, someone would sit down and want to chat with me about architecture, languages or data. PDC is so big and there's so much to talk about with people and there are so many experts here. I've had a lot of folks come up to me and tell me they read this blog, so I thank them!
I hadn't planned on going to PDC but I decided to drive the 5 hours down to L.A. from the Bay Area so I could spend some time with Alan. Our schedules for the past month were so busy that we hadn't seen much of each other. So I thought a road trip in my new car (old one still for sale :-)) would be fun. Alan and I love road trips and we literally flew down I-5.
I admit, I miss L.A. a little bit. I was born near the L.A. Harbor in San Pedro and lived there until I was 19 years old. Driving from Studio City to downtown to Hollywood and flying around in the car has been so much fun. I love how all the freeways are intertwined like snakes and at 2am in the morning you can fly over them so fast -- reminded me of Project Gotham on the XBox :-). The freeways are all named based on the direction you want to head (i.e. Harbor Freeway is south, Pasadena Freeway is north) and you pay respect to the freeways by always saying "the" in front of the freeway number. The 405. The 110. The 101. (In the Bay Area we have public transportation via BART so we don't do that. LOL.) Driving a freeway here can be a lot of fun or a lot of pain depending on the time of day. I slipped right back into my super aggressive driving skills the minute I came into the Valley. I hope a CHP officer isn't reading this post. (Oh and "Sorry" to Sam Gazitt -- apparently he's not used to driving quickly so he was easily scared when I gave him a lift back to his hotel.)
We're staying out in Studio City near Universal Studios and the conference is downtown so I get to drive 12 miles to the conference over 101 into Hollywood then 110 .. oh sorry "the" 110 ;-) into downtown. Not too much traffic so far. At least I don't mind it too much. The weather is warm (high 80's) and the sun is shining bright. Hey -- it's L.A. The weather is always warm here.
The first day at PDC was awesome. Here's the site by the way where all the content is being recorded. I went to the Ray Ozzie Keynote and behind us was Carl Franklin. I snuck a shot as he was intently listening to Ray.
The big announcement on Monday that I'm sure you've heard about already is Windows "Azure" which is all about "data in the cloud". Microsoft has thousands of computers in data centers all over the world where you can program against Live services as well as store data and synchronize it across all your devices and users. It's pretty cool and I'm going to start looking at it myself. You can sign up for an account at www.azure.com to start playing with it. This could be a great solution for small/medium businesses that can't (or don't want to) manage applications and servers on site.
After the Keynote I saw the Channel 9 dude and had to get a picture since I'm a niner as well.
Most of the time I've been spending in the "Big Room" hanging at the Visual Studio booth area but I also have been trying to make sessions. I went to a couple sessions that spoke about the framework used to program against the cloud as well as the Visual Basic Futures talk where Lucian and Paul showed us the upcoming VB 10 features -- no more underscores people! :-) Lucian also showed multi-line and statement lambdas, automatic properties, collection initializers, generic variance as well as a feature called no-PIAs. No-PIAs means no Primary Interop Assemblies anymore. So say if you are working with Office you don't have to distribute the PIAs with your app. Instead the compiler will automatically link in only the methods from the PIA that you are using, thus reducing the deployment burden. Very handy!
So of course there are a lot of MVPs, press, and community people here so I've been having a lot of fun networking as well. I I was supposed to help out with a Chalk Talk on VS 2008 Tips and Tricks yesterday but there were more staff than attendees so I sat down with Michael Palermo, Regional Director in Phoenix and showed him a bunch of features and tricks with XML Literals and LINQ in Visual Basic. He runs a training company and he's going to incorporate the stuff I showed him into their curriculum. He was very grateful for the one-on-one time -- it was no problem, it's what I enjoy most about coming to conferences.
PDC also has cool exhibits. Here's Alan and Steve Lasker next to the Mars Rover.
Sara Ford was at PDC promoting her Visual Studio Tips book where all proceeds go to charity.
I also ran into John (Iron) Lam and Kate Gregory as well as a couple other C-men ;-)
Here's Maurice and Alan playing on the escalator.
On Monday night DevExpress also got Mini Me from the Austin Powers movies to help do a presentation on stage. It was hilarious.
On Monday evening I went to the C# & VB MVP dinner and had some great conversations with many of the language MVPs. We chatted mostly about what business applications they were building lately and what technologies they were excited about most at PDC. I sat next to Paul Vick, Ted Neward and Chris Williams. Charlie Calvert and Lisa Feigenbaum C#/VB Community Leads put the dinner together and it was a hit.
Last night the attendee party was at Universal Studios and it was awesome. They transformed the sound stages into freaky Halloween mazes with awesome actors, I highly recommend it. I love being freaked out. I got a lot of great ideas for my Halloween Party on Friday night :-)
Well I better get back to the sessions, I need to suck up as much knowledge as possible today. Don't forget to head to http://microsoftpdc.com/ for all the content from the conference.
Microsoft Developer Labs has released Small Basic, a simple programming language based on BASIC and a development environment that runs on Windows XP or Vista (written in WPF on the .NET Framework 3.5). There's good documentation and examples as well as a Forum to ask questions and post your cool programs.
I got so addicted to this today playing with it. Here's a simple program I wrote to grab random World Series pictures from Flickr and create a collage.
'
There's no debugger support yet so if you get a runtime error it's hard to debug at the moment, but they plan on adding that soon. I think it would also be very cool to make it more interactive (ala dynamic language) so that as you typed your program actually executed line by line. I'm going to take this to my mom's elementary school when I go speak to the kids this year.
There's even a Turtle in there that you can program to draw on the screen just like LOGO. Very cool! Try this out on your kids and post your feedback to the forum.
If you missed it, yesterday we released a new community submitted article onto the Visual Basic Developer Center and the Office Development with Visual Studio Portal by MVP Alessandro Del Sole. In this article learn how to control the Vista operating system's speech recognition engine in .NET from a custom task pane in Microsoft Word 2007. This article compliments Alessandro's previous article on a text-to-speech add-in for Word 2007.
In this interview Saaid Kahn, a Program Manager on the Visual Studio Pro Tools team (and former member of the VB Team), shows us how to create an n-tier application against a database using ADO.NET Data Services (Astoria) and an Entity Data Model, both now available in Visual Studio 2008 Service Pack 1.
ADO.NET Data Services use WCF REST-ful services and provides all the plumbing so you can focus on the program logic by programming against a service proxy. ADO.NET Data Services allow you to easily create data services exposed on the web using URIs to point to pieces of data and simple, well-known formats to represent that data.
Saaid shows us how to create a simple service and then consume it using a Windows client via the "Add Service Reference" dialog in Visual Studio. He also walks through the client proxy methods that work with the data service.
ADO.NET Data Services (Astoria) in Visual Studio 2008 SP1
I've had a lot of questions lately on how to display data from two separate tables in the database into a single DataGridView for editing. It sure would be nice if all our data was in a single table, but in reality most of the time it's not. Basically the problem is that we want one single table (entity) representation on the client even though we have two physical tables in the database holding the information... thus we need to "split" the data in our entity on the client side into two or more physical tables on the server. There are many ways you can do this depending on the relations in the database and also depending on what your client-side data source happens to be. I'll present a simple, common database table scenario and then attempt to explain how we can work with it using DataTables, LINQ to SQL classes, and then an Entity Data Model --- three different approaches to working with data in Visual Studio.
So let's take a very simple example. In my database I have two tables with a one-to-one relationship, Customer and CustomerContactInfo, one storing basic information about a customer and another that stores contact information:
Entity Splitting DataTables
If we're using DataSets in our application already we probably want to represent this as a single Customer client-side DataTable. To do this, we need to specify some stored procedures in our database for Select, Insert, Update, and Delete so that when ADO.NET retrieves our data or sends back the updated, inserted and deleted rows to the database, it calls our stored procedures that do the work of splitting the data into the proper physical tables. You can easily map DataTables in the DataSet designer to stored procedures. In our example these stored procedures are going to be very simple:
CREATE PROCEDURE [dbo].[GetCustomers] AS SELECT cust.CustomerID, cust.Title, cust.FirstName, cust.MiddleName, cust.LastName, cust.Suffix, cust.CompanyName, cust.SalesPerson, contact.EmailAddress, contact.Phone FROM [dbo].[Customer] AS cust JOIN [dbo].[CustomerContactInfo] AS contact ON cust.CustomerID = contact.CustomerID
CREATE PROCEDURE [dbo].[DeleteCustomer]( @CustomerID [int] ) AS BEGIN DELETE [dbo].[CustomerContactInfo] WHERE [CustomerID] = @CustomerID DELETE [dbo].[Customer] WHERE [CustomerID] = @CustomerID END
CREATE PROCEDURE [dbo].[UpdateCustomer]( @CustomerID [int], @Title [nvarchar](8), @FirstName [nvarchar](50), @MiddleName [nvarchar](50), @LastName [nvarchar](50), @Suffix [nvarchar](10), @CompanyName [nvarchar](128), @SalesPerson [nvarchar](256), @EmailAddress [nvarchar](50), @Phone [nvarchar](25) ) AS BEGIN UPDATE [dbo].[Customer] SET [Title] = @Title, [FirstName] = @FirstName, [MiddleName] = @MiddleName, [LastName] = @LastName, [Suffix] = @Suffix, [CompanyName] = @CompanyName, [SalesPerson] = @SalesPerson WHERE [CustomerID] = @CustomerID UPDATE [dbo].[CustomerContactInfo] SET [EmailAddress] = @EmailAddress, [Phone] = @Phone WHERE [CustomerID] = @CustomerID END
CREATE PROCEDURE [dbo].[InsertCustomer]( @Title [nvarchar](8), @FirstName [nvarchar](50), @MiddleName [nvarchar](50), @LastName [nvarchar](50), @Suffix [nvarchar](10), @CompanyName [nvarchar](128), @SalesPerson [nvarchar](256), @EmailAddress [nvarchar](50), @Phone [nvarchar](25), @CustomerID int OUTPUT ) AS BEGIN INSERT INTO [dbo].[Customer] VALUES ( @Title, @FirstName, @MiddleName, @LastName, @Suffix, @CompanyName, @SalesPerson ) -- Get back the customer ID SELECT @customerID = CustomerID FROM [dbo].[Customer] WHERE @@ROWCOUNT > 0 AND [CustomerID] = scope_identity() INSERT INTO [dbo].[CustomerContactInfo] VALUES ( @customerID, @EmailAddress, @Phone) END
Now that we have that set up, open up the Data Source Window in Visual Studio and add a new data source, select the Database and then select just the GetCustomers stored procedure:
Click Finish and then open up the DataSet designer by double-clicking on the CustomerDataset.xsd in the Solution Explorer. You'll notice that the name of the DataTable is GetCustomers so change that to just "Customer". Next we need to configure the DataTable so that it will use our stored procedures so right click on the DataTable and select "Configure...". The TableAdapter Configuration Wizard should open and this will allow you to map your stored procedures to the Update, Insert and Delete commands. By default the fields will match up by name so you shouldn't have to do anything but drop down the combo boxes and select the right procedures for each action.
To test this out you can drag the Customer table from the Data Sources window on to a Windows Form as a DataGrid and immediately run it.
You will see the data from both tables displayed in the grid and they will be editable. As you update, insert and delete rows here, the DataSet will keep track of these changes for you. So when it is time to save the data via a call to the TableAdapterManager.UpdateAll method, the proper stored procedure will be called for each row that was modified.
Entity Splitting LINQ to SQL Classes
So with a Dataset, the DataTables do not have to map one-to-one with your database tables, but you need to specify how the data should be saved back to the database via stored procedures. This is also true if using LINQ to SQL classes. In that case though, you drag methods onto the method pane first and then map them to the class in the designer by right-clicking on the class and selecting "Configure Behavior...".
However with LINQ to SQL classes you can't map the Select behavior unfortunately. What you do instead is map the result of the GetCustomers method to a result type of Customer (the class we created on the design surface). Then when accessing the customers data you need to remember to call the GetCustomers method and not access the Customers directly in the DataContext, otherwise you'll get a SQLException that it cant find the additional columns when retrieving the data (in our case EmailAddress and Phone).
Private db As New MyDataContext Private SubForm1_Load() Handles MyBase.Load 'This will properly populate a collection of our ' Customer entities. Me.CustomerBindingSource.DataSource = db.GetCustomers End Sub
To save the data in a connected state like this we can simply call SubmitChanges on the DataContext. The LINQ to SQL DataContext tracks the state of each modification, deletion or insertion into the collection of Customers and will call the corresponding stored procedures that we configured.
Private Sub CustomerBindingNavigatorSaveItem_Click() _ Handles CustomerBindingNavigatorSaveItem.Click Try db.SubmitChanges() MsgBox("saved") Catch ex As Exception MsgBox(ex.ToString) End Try End Sub
(Note: In order to get get drag-drop data binding in Windows Forms to work with LINQ to SQL objects you need to select Data --> "Add New Data Source" on the main menu, then select Object (not database). Then select the Customer object and Finish. This will populate your Data Sources window so you can drag the grid onto a Windows form.)
Entity Splitting Using the Entity Data Model
This scenario becomes pretty straight-forward and automatic using the Entity Framework (EF) and you're not required to write any stored procedures to get it to work. This is because EF provides more complex mappings out of the box than LINQ to SQL or DataSets. And EF separates your database schema from your object model by providing a mapping layer. If you have Visual Studio 2008 Service Pack 1 you can create what's called an Entity Data Model which provides an ObjectContext, similar in theory to the LINQ to SQL DataContext above, but it provides many more mapping features.
When you add a new Entity Data Model to your project you can choose to generate it from the database or you can create an empty model. For this example I'll choose to generate it from the database and I'll select just the Customer and CustomerContactInfo tables and no stored procedures this time. (Note that I can still map stored procs to the update, insert and delete behaviors if I need to though.)
This looks just like our database model except you can see the navigation properties displayed that let us navigate from one entity to related ones. Notice the association is also shown as one-to-(none or)one. To set up the mapping so that it will automatically split the entity for us first we need to adjust the Customer by adding the EmailAddress and Phone. You can select the EmailAddress and Phone properties of the CustomerContactInfo and cut then paste them into the Customer. Then you can delete the CustomerContactInfo class from the design surface.
Now select the Customer and look at the Mapping Details window. Below the column mappings you will see <Add a Table or View>. Drop that down and select CustomerContactInfo and it will automatically map the columns in that table to the properties that we added.
Save the model and rebuild the project. Now you can add Customer as a data source for drag-drop Winforms data binding the same way you do for LINQ to SQL classes or your own objects. And the code for loading and saving of the Customers is similar to the LINQ to SQL code above except loading the Customers is much more intuitive. And the ObjectContext tracks changes for you and generates the proper insert, update, and delete statements automatically without you having to define stored procedures to do the splitting.
Private db As New MyDatabaseEntities Private Sub Form1_Load() Handles MyBase.Load Me.CustomerBindingSource.DataSource = db.Customer End Sub Private Sub CustomerBindingNavigatorSaveItem_Click() _ Handles CustomerBindingNavigatorSaveItem.Click Try db.SaveChanges() MsgBox("saved") Catch ex As Exception MsgBox(ex.ToString) End Try End Sub
This is just the tip of the iceberg using the Entity Data Model. I'd recommend reading the documentation in the MSDN library, visiting the forums and the FAQ, as well as visiting Julie Lerman's site (she's been living EF since the early Betas). I'm just learning EF myself but as you can see it allows you to model more complex data scenarios.
On Wednesday the conference organizers of the SDN Conference took the speakers on a Holland Tour. We left the conference center and hotel in the morning and headed to Rotterdam. I got to ride with Maurice in his little green Miata, very fun! The countryside is just beautiful and very green.
It didn't take us long to get to our first destination, a boat that would take us on a harbor tour. This harbor is the largest in Europe and I was told the second largest in the world. They fed us cake and coffee and we cruised around the entire harbor.
I grew up in southern California near the port of Los Angeles so the container ships and cranes reminded me of my childhood.
It was a little chilly for me but it wasn't raining so I got a lot of great pictures. The architecture of the bridges in Rotterdam is amazing. I took these shots of the Erasmus bridge just as we were passing under it. Maurice also has a great shot of the bridge. I also took shots of the lesser famed "red bridge", I think it's called the Willems bridge. There are a ton of draw bridges too.
There were also a lot of interesting ships with a single car on top of them. I was told this is because the captain and his family live on the ship and so they park their cars on the top of them.
After the harbor tour we went up into the Euromast, a high tower that looks over the entire city (kind of like the Seattle space needle). There's a restaurant up there and that's where we had lunch. Then we walked outside and up a couple scary flights of stairs a little more than halfway up the tower. That's where we caught a ride in this rotating chamber that took us all the way up to the top. It was amazing.
Next we headed to Amsterdam to visit the largest soccer stadium in the Netherlands, called Ajax Arena (catchy name ;-)). I'm actually a huge baseball and American football fan so this tour was pretty fun for me. However, I think the tour guide realized that were were a bunch of computer nerds so he focused on the technology that runs the stadium more than the team itself.
At the end of the tour we went into the press room and I got up and pretended to give a speech on how I blew the game :-)
After the tours we headed to a "beach house" on a lake where Remi, Steven and Carl made us ribs and burgers. I have to say that this is an amazing and beautiful country and the people are great. It's really easy to find fun here and I definitely recommend a vacation to this beautiful area of Europe.
Today I woke up at the crack of dawn because I had an 8:30 AM session. Okay maybe not quite the crack, but for me it was early. Especially after a night of socializing. That's a really cool thing about conferences here, the attendees love to go out with you after dinner and uh.. socialize. ;-) There were a lot of great conversations about technology flying everywhere it was hard to keep up. I crashed about 1 AM (which everyone told me was early!) and woke up about an hour and a half before my talk, no problem.
This talk I've done many times before and it's one of my most favorite subjects -- XML Literals and LINQ to XML in Visual Basic. I've done variations of this talk at user groups, other conferences and webcasts. And I showed a lot of the techniques that I've written about here as well as this article and this one. This was my best session according to the ratings but it's so easy to do well with this talk because of the simple and powerful expressiveness of XML in VB. It doesn't take much code at all to start creating, querying and manipulating XML documents directly in the editor with this awesome feature. Check out the VB Team blog where Doug Rothaus is doing a series of posts on XML in VB.
I also attended Brian Noyes' session on WPF Data Binding. Since I've been speaking about this as well I thought I'd join him and compare notes. ;-). I also told him about what scenarios I was going to tackle next on my WPF Forms over Data video series and he validated where I was going with it. It's great to chat with experts building business applications because I've built many in my life as well and the challenges are always similar. Brian is one of my data binding heroes since he wrote his Data Binding in Windows Forms 2.0 (which I still highly recommend).
Although there were a ton of .NET sessions, there were also a lot of Delphi sessions as well as a co-conference DotNetNuke OpenForce at this venue. I met a lot of cool people in the software industry.
The final wrap up was a bunch of cool give-aways for the attendees including a Wii and a Blue-Ray disk player -- very cool! I took a few pictures of some of the speakers and organizers...some of them acting pretty goofy.
Tomorrow I head back to Amsterdam where the organizers are going to take the speakers on a Holland tour. I can't wait!
I'm here in the Netherlands in a town called Noordwijkerhout near Amsterdam at the SDN Conference with a lot of great speakers and sessions.
I took these shots while the attendees were in session. There's good food, great vendors and lots of entertainment -- XBoxes, bowling, pin-pong, and lots of bars ;-) We also had a really funny English comedian perform at the end of the night. The Dutch really know how to put on a great event.
I have a total of three sessions and two on the first day. First I did a session called LINQ to Everything where I walked through each of the LINQ providers in Visual Studio 2008 SP1 "box" including LINQ to SQL, LINQ to DataSet, LINQ to Entities and LINQ to XML. We discussed application architecture and considerations and I showed demos to introduce each of the technologies. The room was packed and I got great scores so I'd say it went well. :-)
Next session I did was a lot of fun. It was called Taking Advantage of LINQ and Open XML in Office 2007 and I showed how to manipulate Open XML document formats in Office 2007 Word, PowerPoint and Excel documents using the Open XML SDK version 2.0 and LINQ to XML. I think it sparked a lot of people's curiosity and creativity because there are a lot of possibilities. I showed how you can create, query and transform documents without having to have Office installed at all. I also had great reviews and chatted with many attendees afterwards who were building a lot of cool business applications.
I attached the presentation and demos so have a look.