November 2008 - Posts

Sometimes those transaction logs get a little large and unwieldy!  For dev machines I almost never want the transaction log to ever be larger than 1GB.  I often find some transaction logs of 10GB and larger and there is little in the way of GUI tools to help you free up that wasted space.  Luckly there is a really good command for SQL Server 2005 & SQL Server 2008 that will allow you to truncate the existing transaction log.

DUMP TRAN [DATABASE_NAME] WITH TRUNCATE_ONLY

That's it!  You would think they would include a button or something in SQL Server Management Studio, but as I understand it this would be a bad thing to do in a production environment.

Hope this helps someone -- if so leave a comment!

EDIT:

If you are doing this is SQL Server 2008 then it no longer recognises the DUMP command.  The best way to do this going forward is:

ALTER DATABASE [DATBASE] SET RECOVERY SIMPLE

The problem with this approach is that it will change your recovery mode from whatever it was to 'SIMPLE'. You will need to chage the recovery mode back after you run the command.

Singularity Singularity is a Managed operating system started by Microsoft Research.  It's last version 1.1 target the .NET 1.1 framework and was a very fast OS (if not all that functional).  The latest version supports the 2.0 framework, 64-bit processing, additions to the Bartok (MSIL-to-native) compiler, and updates to the Sing# compiler (C# style language used to build the Kernel).

 

Here is the architecture map of the project:

SingularityArchitecture

Some of the interesting things about Singularity are:

  • The use of Managed code in the Kernel (also includes a small amount of C and assembly, but not much); therefore device drivers can be build using a C#-style language called Sing#.
  • SIP's (Software Isolated Processes) means that processes don't communicate without a "Channel", they are also not allowed to share memory directly or change their own code.  They are also very lightweight and allow the operating system to make guarantees about running code.
  • Channels are interfaced-based process communication that are meant to be safe and fast
  • Static Verification is used before starting a SIP to verify that the code that is about to be run "follows the rules" of the operating system.  This helps eliminate "harmful" code -- that is code that has a negative effect on the system as a whole.

You can download the RDK here.

Links:

I have been wanting to add JavaScript to my posts for months but have never gotten it to work.  I can usually get around using JavaScript but I decided that I wanted to add a Digg tag at the bottom and that requires some JavaScript. 

 

  1. Open the communityserver.config file in the root of the Community Server 2008 install.
  2. Remote the line that reads:
    <add name="WeblogPostandArticleHtmlScrubbing" type="CommunityServer.Blogs.Components.PostandArticleHtmlScrubbing, CommunityServer.Blogs" />

Links:

 

with no comments
Filed under:

I had a problem connecting to my companies VPN a while ago.  I found running the following helpful:

Uninstall PPTP & L2TP Protocols:

Windows PowerShell
Copyright (C) 2006 Microsoft Corporation. All rights reserved.

PS C:\Windows\System32> netcfg -u MS_PPTP
Trying to uninstall MS_PPTP ...

...done.

PS C:\Windows\System32> netcfg -u MS_L2TP
Trying to uninstall MS_L2TP ...

...done.

Re-install PPTP & L2TP Protocols:

PS C:\Windows\System32> netcfg -l c:\Windows\inf
etrast.inf -c p -i MS_PPTP
Trying to install MS_PPTP ...

...c:\Windows\inf
etrast.inf was copied to C:\Windows\INF\oem69.inf.

...done.

PS C:\Windows\System32> netcfg -l c:\Windows\inf
etrast.inf -c p -i MS_L2TP
Trying to install MS_L2TP ...

...c:\Windows\inf
etrast.inf was copied to C:\Windows\INF\oem69.inf.

...done.

 

Presenter: Joe McBride

Date: Thursday November 13, 2008

Place: Neumont University

 

I am pretty excited about this.  I am a big fan of design patterns and the presentation promises to cover MVC and MVP design patterns and those are not well understood architectures and I was also interested to see how it was applied to WPF.  There is also an additional pattern described called "Model View ViewModel"(MVVM).

Model View Controller (MVC)

This model seemed to be presented a bit differently than I expected.  The slide suggested that the Model could somehow be used circumventing the presenter.  Regardless, the MVC was described much like an API that is available for the view to consume passing nicely typed domain objects back and forth. This is a pretty straight-forward design pattern and has a lot on common with nTier. 

One of the good things about MVC is that it is much easier to test.

Model View Presenter (MVP)

The view can raise events to the presenter and everything is marshaled through the presenter.  One of the pro's about MVP over MVC is that data binding is made possible. The presenter becomes the gateway for any logic -- the object you are using to bind with doesn't need to be a domain object but can be a UI object. Data binding is the coolest and least understood part of WPF and I believe that Data binding could have been applied with the MVC pattern but the MVP is clearly easier.  The binding statements were very simple and the code looked pretty clean. 

One thing that I might not like about MVP is that the objects returned may be too customized for a particular view and if you plan to deploy this code with multiple views, for WPF and ASP.NET for example, may need entirely different types of objects for data binding.

Command Pattern

The command pattern is a lot like a fire alarm.  When there is a fire someone pulls the fire alarm and everyone exits the building.  In this analogy the fire alarm is the "command", it is invoked by someone pulling it and anyone could pull it.  When it is pulled everyone interested in the fire alarm takes appropriate action.  This is actually an analogy I came up with on the fly but I think it's a great way to describe a pretty abstract concept. 

Model View ViewModel (MVVM)

This is a new pattern to me -- I have never even heard of it before.  I do think that this approach could have some advantages where the ViewModel could be customized to work better with the actual view.  This is also a good place to implement the command pattern.  It is also a very useful that commands can be disabled which makes will actually update the WPF UI! That is pretty awesome!  The only potential downside (if you choose to call it that) is that there seems to be mode code involved even if it is somewhat abstracted away from the UI. 

Testability

Part of a good measure for any presentation design pattern is how testable it is.  I really believe that if you can keep your UI code to a bare minimum that the unit tests will be substantially more effective. 

Observations:

  • I like the microphone. 
  • Great turnout.  I counted about 45 people in attendance
  • It's very un-impressive when in the first 30 seconds of the presentation the code is broken; it was fixed very quickly though.
  • Too much on a single slide.  Could have done well to split them out into two or three slides.
  • Pizza was gone by the time I got there....bummer!  Probably makes my review more critical -- I need Pizza!
  • I think it could have been possible to do this almost entirely via Commands which would eliminate any code required on the code-behind for the view.  That might be an interesting thing for me to try later.
  • I was shocked when Charles Petzold's book was not mentioned as a good WPF resource!  Geesh!  Also, I don't believe Adam Nathan's book (WPF Unleashed) is difficult and fast-paced.  I actually found it a quite addicting read.  Maybe not so much for the writing style (Petzold is clearly the literary master of the two) but because WPF is just such an interesting subject.
  • I couldn't believe how few people know what the Command Pattern is.
  • I would like to have seen more interfaces and loose cohesiveness.  Okay -- Nevermind!  Just as I typed this he showed that he was using an interface.
  • I was very disappointed to see the use of var where objects are not anonymously typed. 
  • The presentation didn't seem to flow too well at times.  I was also hoping to see a bit more of the mock objects and how to create those for unit testing.

Summary

Thanks Joe! Great presentation.  Very good demonstration code used and it was very simple and small.  I have to admit I am a little jealous of your blog domain and I think it's cool that he got it and that he actually uses it.  Hopefully we can link to each other more in the future.

 

Links:

ie8_logo For the last few months I have been testing out IE8 and for the last few months I have been testing out Google Chrome.  I actually reviewed Chrome in a previous post and concluded that there probably wasn't any real reason to migrate from what your are using already.  I think I may be changing my mind.  The more I use the software the more I am convinced that IE8 is going the wrong direction!  After reading an article in Redmond Magazine (I believe the title to be sarcastic).

The basic premise of the article is that the web is looking for small incremental change, not catastrophic change.  I don't entirely agree. We don't want our web applications to break too badly, but at the same time we want massive change and innovation in our browsers.  We want light, fast, safe, and secure.  It's not that I have any problem with any features planned for IE8 per se, it's just that I can see they are not spending time on my first two requirements -- fast and light!  I do have a problem with one of their features as I select text periodically when reading it and some new feature gums up my reading routine. 

Basically, my experience with IE8 can be summed up with this statement-- Slow and Unusable, even for Beta.  I much prefer IE7 to IE8.  So if any of the IE8 team end up reading my blog, my message is this:  You still have plenty of market share and plenty of time to do this right.  You do not want to rush to release something that is going to reduce market share.  Take a page from the Firefox book, a page from the Chrome book, and write a few of your own pages.  Lead, Follow, or Get Out of The Way!

In case the team has run low on new and exciting innovations I spent a day and a half thinking of some really cool features that would get me excited about IE again. 

Innovations:

  • Use V8 (or roll your own version of managed JavaScript -- I don't care, but make it faster!)
  • Allow for any code engine to execute against the DOM like JavaScript.
  • Write the browser in managed code for performance and safety
  • Re-work the plug-in model to operate from an interface and run these plug-ins in such a way that they can not kill the browser or even the current page
  • Make it easy to make plug-ins!
  • Allow the interface to be skin-able
  • Allow users to see what is happening with resources used; which plug-ins and pages are causing problems.
  • Multi-thread the browser; I.E. Never (and I mean never) block the UI thread!  JavaScript should not be run on the UI thread.
  • Allow for C#  script; while not entirely useful for wider deployments it can be useful for enterprise apps.
  • Get fully standards compliant (this doesn't seem that difficult); although I don't entirely agree with all of the standards.
  • Update the "Find" dialog! FOR THE LOVE OF PETE, REFINE THE FIND DIALOG! Update: I had forgotten that they actually did replace the find dialog with a Firefox-looking dialog that I liked much better.  I don't remember if it had a highlight all (as I uninstalled it a week or two ago), but if it doesn't -- it should. 
  • Update the download dialog.  It should, at the very least, support:
    • Download Resume
    • Start the download--then ask me where I want to save it. 
    • Allow users to create some kind of convention about the default save path of a file.
    • Allow more than 2 concurrent downloads per domain or at least allow the user to easily set that setting.  I know this is a standard, but overlook it! Update: According to a rather abrasive and defensive person on the IE8 forum it supports 6 simultaneous downloads; I wonder if it's possible if IE7 emulation mode made a difference?  If not it could simply have been the server, the network, etc. 
    • Allow downloads to be queued.
    • Allow downloads to be throttled.
    • Don't block downloads!  Allow the user to set a policy if they want to block executable downloads, but even if the download is blocked, don't make the user have to refresh the page to get it to download!
    • Don't kill the download after the save file dialog. Is this a bug?
  • Maximize the screen real-estate, but keep the basic stuff visible.  Hiding the menu's in favor of a toolbar was a bad idea.
  • Store the cookies and history in a Relational Database rather than a ton of files.  Firefox uses SQLite.
  • Allow the history to be quickly searched.
  • Show more informative error screens.  Was the browser unable to resolve the DNS?  Was it not able to connect?  Did it get an error code and if so, what?
  • Re-Do browser integration for 3rd party applications.  ActiveDocument STINKS!
  • Allow book-marked pages to be fully downloaded and updated.  Also the user should be able to "save their bookmarks to the web"
  • MAKE IT FAST AND LIGHT!
  • Continue to innovate!   There is no reason to make a browser that is the same as any other.

UPDATE

I kind of walked into this one by posting a link to this post on the IE8 blog.  I was immediately "ripped into" for two of my inaccuracies (noted above) and was left with a comment that concluded that my opinion was uninformed and somehow irrelevant.  This person may or may not actually be from the IE8 team, but he did speak somewhat authoritatively on the subject.  Besides two of the noted exceptions above he (along with many others, even at Microsoft) though the notion of a managed browser was ridiculous.  Because I listed performance as a potential benefit of managed code he pointed out that there isn't anything that can be done in Managed code that can't be done in native code.  So I guess that means that IE8 has it's own memory manager which can move blocks of memory around in an efficient manor and can re-size existing blocks in the heap?  Seeps pretty unlikely as this would mean they would have to give up pointers in C++ and that is really, really, really unlikely.  They must also have some way of preventing all code-based security exploits so apparently we won't see any patches for IE8 once it has been released.  Humm, nice to know!

Incidentally, I have started a series of blog posts that compare relative performance between managed and unmanaged code.  At the time of this writing I have only the first post but I have written experiments for the next two and I can say at this point that where C++ wins, managed code isn't far behind; whereas where managed code wins, it wins big!  My experience is that hard-core C++ programmers really hate managed code, usually listing performance for the reason.  I suspect that the real reason is they are loathe to give up 'total control', especially when it comes to memory management.

I doubt my comments had any effect on anyone -- let alone anyone in charge.  So I hope MS doesn't pull another Vista!

Links:
Cuegle.com Project Screenshots: Smart Forms Advanced Document Center
with 1 comment(s)
Filed under:
Nathan Zaugg SUMMARY A dedicated individual with years of experience in computer programming/engineering. A dedicated member of the local technicial community with excellent leadership and training skills developed over 4 years as a consultant. SKILLS...
with no comments
Filed under:

SOA Service Oriented Architecture is a software design concept that packages small pieces of modular functionality into "services" through the software lifecycle.  SOA separates functionality into a set of self-contained, modular units that can be combine by a simple application to accomplish a task.  This blog post will focus on a few specifics of SOA but will mostly discuss the benefits of using SOA in the Enterprise.

Background

One of the main pieces of philosophy that SOA embraces is the KISS (Keep It Simple & Stupid) principle.  The fact is that big complex projects fail while small, simple projects succeed.  As a developer I see this every day.  For example, a few months ago me and my friend Phil wrote a web site.  In the early days and weeks (after getting some of the basic requirements ironed out) functionality was really easy to add.  Everything existed in a very simple state because it was a simple design with simple requirements.  We finish the original set of requirements pretty early in the project when they decided that we wanted to do some enhancements.  These enhancements greatly complicated the application.  Now, adding even a small amount of functionality takes substantially longer.  Over the weekend I wanted to add the ability to add category in as part of the search.  In the early days of the project it was actually work to leave it out (I had to disable the box when they changed the type of search).  It was pretty easy to add it into the stored proc but then the coding changes!  I had to add it to my data layer, data model, view, and controller.  Of course, these changes broke some other functionality that was added after this feature was originally included.  Because Unit Testing wasn't going to be part of the timeline we have to test a large portion of the site to be comfortable that this change didn't break anything else.  The two universal facts are that:

  1. The larger and more complex an application becomes the longer it takes to add features.
  2. Changing code is more expensive that writing new code.

In Juval Lowey book called Programming .NET Components he highlights that component-oriented programming can simplify and add flexibility to complex applications.  He also makes a good case for simple software and all of these concepts port directly into the SOA paradigm. 

What is a service?

When many people hear the term "service" they almost always either think of Web Service or Windows Service.  The truth is that a service can be almost anything that provides implementation to a consumer.  In this context a service can be a library that can be invoked (much like Win32 API), or it could be a piece of hardware that performs complex calculations (like a Graphics Card/GPU).  Believe it or not the World-Wide Web is just a bunch of different services.  Web services have been particularly popular as they meet the criteria for usability.  1) Universally accessible, 2) Simple and Stateless.  In addition web services are easy to deploy, change, and have an already extensive existing infrastructure.  Web Services are also very scalable and are easy to make redundant which provides high availability.

 

Application Architecture 

Figure 1: Enterprise SOA Diagram

 

Why SOA?

Besides the benefits from rapid software development there are many other benefits of SOA.  For those looking to make a business case of ROI consider that SOA helps to make your company easily and quickly change business processes to align with market conditions.  This is because the software is now modular and flexible and especially if you use some type of workflow for your complex business tasks these rules can be easily updated and changed.  Also, new functionality is quickly developed, integrated, and deployed.  Consider the difficulty involved in making a change in the order in which orders are filled.  With a Fat-Client approach you may have several different apps that depend on the order being predictable.

Testability

Testability is arguably one of the best benefits gained by the SOA approach.  Because we have a simple granular piece of functionality it makes testing of this functionality easy.  It is also easy to test as these smaller functions are designed to be exposed.  It can be difficult to test code that wasn't intended to be consumed.  In terms of change management, if we keep our business running in services then our unit tests can help guarantee confidence in a new release of an application that uses several different services.

Because the database is only touched by one layer of our enterprise application infrastructure and due to the fact that most services will exclusively deal with a small subset of tables -- changes to the database become greatly simplified in a true SOA environment.  This adds simplicity and allows the company to change more quickly to adapting demands on their business.  In addition different systems can be allowed to run on different databases which makes migration from one database to another significantly simpler.

Security

Security is a great reason to move toward SOA.  The biggest gain is that the Database servers can be safely tucked in a Back End Zone (BEZ) because our applications no longer need to connect directly to them.  This is also extremely helpful if you have each user connect to the database using Integrated Authentication or an account unique to each.  This will cause hundreds and thousands of connections on the database and reduce performance substantially!  Moving the database into a zone where it can only be accessed from the application servers limits the surface area for attack and greatly limits potential venerability.  For financial systems it is part of the infamous Sarbanes-Oxley (SOX) audit to prohibit access directly to the database (in addition to change logging requirements).  While this is not the only way to come into compliance with a SOX audit it is arguably one of the better ways. 

Simplicity

Again, the best benefit of SOA is the simplicity each service can have which results in less bugs, more developer productivity, modular reusable code, and flexibility.  Services should be broken up into a lot of different chunks to make them easier to manage and they should typically include only one concern (a single aspect of the business).  Other services can consume existing services to expose more complex business sceneries. 

"It breaks down the complexity of software systems by isolating services.  This simplifies configuration management for each piece, and whole applications can be made compliant with new ordinances and business requirements without updating any of them." -- Phil Gilmore

Another benefit SOA gives us is that every call needs to have an interface that is carefully and purposefully designed.  Using Interfaces is a great way to promote loose-cohesion and makes changing different parts of the code much easier to accomplish.  So long as any changes you make can still be supported by the interface already defined most changes are inconsequential.  If you must make a change to the interface of a service you will typically be doing this to add new features and usually the existing interface can be left alone and a new version of the interface can be supported for that service. 

"SOA has a downside in version control.  Services must usually be able to run side-by-side versions to support applications whose requirements don't change synchronously." -- Phil Gilmore

Performance

Performance is an important consideration when talking about services (especially web services) and potential impact to application performance.  Network round-trips are expensive -- even in a LAN environment.  Also the serialization and de-serialization of objects adds extra time for each call -- time that is not necessary when using a framework-style call.  While all of this is true, consider that any data retrieval is expensive.  If your application connects to a central database you still incur the overhead of connection to the database over the network, your data is still serialized as it goes over the wire and you will usually still hydrate objects with this data once you get it back.  At that point the only layer that a web service has that is extra is that of IIS.  When you factor in the connection pooling that can be accomplished on a service with the cost of having many (and perhaps even thousands) of concurrent connections to the database when thick clients connect directly it's easy to see that your probably not going to see any significant performance loss by moving to this type of architecture.  It may take some getting used to when creating calls with a ton of parameters but it will perform well.

Another thing to consider when looking at performance aspects of SOA is that a web service written with WCF is fast!  How fast? I haven't benchmarked web services in .NET for quite a while (since Framework 1.1), but I know there were significant performance gains for the 2.0 Framework and even more gains for 3.0 & 3.5 Frameworks.  Additionally, the newer frameworks have much lighter formatters and endpoints than we did back then.  Keeping this in mind, back when I benchmarked a simple web service that would reverse a string that was sent to it as input that service was ran at a rate of 2,200 calls per second sustained!  This is a testament both to IIS as a middleware server and .NET Web services for sheer speed!  Our other web service was coded in Delphi 7 as an ISAPI DLL and struggled to sustain 10 calls per second.  The Delphi service also intermittently failed whereas the .NET web service did not.  In short, the web is a great way to expose a service and there is little need to look for anything "faster" or "more robust". 

Configuration Management / Distribution

When looking to other positive aspects of SOA, without a doubt one of the best arguments is distribution.  The race to "web enable" everything possible is a landmark of the difficulties of distribution.  These so-called thin clients relegate any deployment and configuration to the server that runs the service.  This concept of "configure once" is embraced by SOA.  If you plan on deploying a smart client (a cross between a thick client and a thin client) significantly reduces the amount of configuration required for users to execute your software.  They don't have to worry about database providers, connection strings, loggers, DSN's, or anything else your app might use.  SOA can even be used for web sites (thin clients) that require these services.  SOA is a principal without a fixed style of client so it will work as well with a web app as it will with a windows app. 

"This saves configuration management by avoiding redeployment of existing applications, it saves software engineering by not modifying the applications, it tends to save time in testing if testing can be isolated to that service rather than testing all applications that consume it." -- Phil Gilmore

Summary

Service Oriented Architecture is a best-practice for today's Enterprise.  It's use can substantially reduce the manpower required to maintain applications and has major improvements to maintenance, scalability, change management, code reuse, and distribution of applications. SOA will make your life easier and make your employer happy and isn't that the most important argument of all?

 

with 2 comment(s)
Filed under: , ,

VS2010

After a whirlwind week of PDC (too bad I wasn't in attendance) Microsoft released CTP bits of Visual Studio 2010.  I hope to post a lot more about some of the features as I go through the walk-throughs, but until I get it downloaded I wanted to share the download link.

http://social.msdn.microsoft.com/Forums/en-US/category/vs2010ctp

http://blogs.msdn.com/charlie/archive/2008/10/27/visual-studio-2010-bits-are-live.aspx

coding_camper Here are the examples I used during my LINQ to Entities presentation.  They show how to use the EntityClient, ObjectQuery, and LINQ to Entities queries.  All examples are built using a 1:1 mapping to the Adventure Works database that had been slightly modified.  The Object Services with Lazy Loading Example shows some how to debug these queries.

Entity Client Example

// Entity Client & Entity SQL
using (EntityConnection conn = 
new EntityConnection("Name=AdventureWorksEntities")) { conn.Open(); EntityCommand cmd = conn.CreateCommand(); cmd.CommandText = "SELECT VALUE c FROM
AdventureWorksEntities.Customer AS
c WHERE c.State = @state"
; cmd.Parameters.AddWithValue("state", "UT"); DbDataReader rdr = cmd.ExecuteReader(
CommandBehavior.SequentialAccess); while (rdr.Read()) { Console.WriteLine(string.Format("Company Name:
{0}\tCompany City: {1}"
,
rdr["CompanyName"], rdr["City"])); } }

Object Services Query Example

// Object Services & Entity SQL
using (AdventureWorksEntities data = 
new AdventureWorksEntities()) { ObjectQuery<Customer> custs = data.CreateQuery<Customer>( "SELECT VALUE c FROM Customer AS c WHERE c.Address.City = @city", new ObjectParameter("city", "Salt Lake City")); foreach (Customer cust in custs) { Console.WriteLine("Company: " + cust.CompanyName); } }

Object Services Query with Eager Loading Example

// Eager Loading with Object Services
using (AdventureWorksEntities data = new AdventureWorksEntities()) {
    ObjectQuery<Customer> custs = data.CreateQuery<Customer>(
        "SELECT VALUE c FROM Customer AS c WHERE c.State = @state",
        new ObjectParameter("state", "UT")).Include("SalesOrderHeader");


    foreach (Customer cust in custs) {
        SalesOrderHeader sales = cust.SalesOrderHeader.FirstOrDefault();
        string str = (sales == null) ? "none" : sales.OrderDate
.ToShortDateString(); Console.WriteLine( string.Format("Company: {0}\tOrder: {1}",
cust.CompanyName, str)); } }

Object Services Query with Lazy Loading Example

// Lazy Loading with Object Services
using (AdventureWorksEntities data = new AdventureWorksEntities()) {
    ObjectQuery<Customer> custs = data.CreateQuery<Customer>(
        "SELECT VALUE c FROM Customer AS c WHERE c.State = @state",
        new ObjectParameter("state", "UT"));

    Console.WriteLine("DEBUG: " + custs.ToTraceString());

    foreach (Customer cust in custs) {
        if (!cust.SalesOrderHeader.IsLoaded)
            cust.SalesOrderHeader.Load();

        SalesOrderHeader sales = cust.SalesOrderHeader.FirstOrDefault();
        string str = (sales == null) ? "none" : sales.OrderDate
.ToShortDateString(); Console.WriteLine( string.Format("Company: {0}\tOrder: {1}",
cust.CompanyName, str)); } }

LINQ to Entities Query Example

// LINQ to ENTIES (Lazy Loading)
using (AdventureWorksEntities data = new AdventureWorksEntities()) {

    var custquery = from d in data.Customer
                where d.State == "UT"
                select d;

    foreach (Customer cust in custquery) {
        if ( !cust.SalesOrderHeader.IsLoaded )
            cust.SalesOrderHeader.Load();
        SalesOrderHeader sales = cust.SalesOrderHeader
.FirstOrDefault(); string str = (sales == null) ? "none" : sales.OrderDate
.ToShortDateString(); Console.WriteLine( string.Format("Company: {0}\tOrder: {1}",
cust.CompanyName, str)); } }

The presentation slides are available here.