Beth's Chinese blog
The first episode in a series on VS 2010 was posted this week on Channel 9. The series is put on by some of my favorite niners; Brian Keller, Jason Olson, Drew Robbins and Jonathan Carter. This episode not only shows you how to download and set up the Visual Studio 2010 VPC but also contains info on how to extend the time bomb past the end of the year by disabling the system clock synchronization between your host OS and the VPC. So if you're working with the VS CTP right now like I am this will come in handy ;-)
Here's more info from Brian Keller and Jeff Beehler:
Visual Studio 2010 CTP VPC: Dealing with Activation Messages
Dealing with the Team System 2010 CTP expiration
Enjoy!
I've been up in Redmond this week for a regularly scheduled office visit but instead of 5 days of meetings I only could get 3 days in. This is because on Wednesday night it started to snow! Yes, it snows in Seattle! I have been coming up here (and lived here for a brief period) since 2001 and it's snowed every year that I can remember. Don't let people fool you ;-)
So I've been house-bound going on the second day. I know there are a lot of snow storms in North America today. I just saw that Toronto is getting pummeled along with NYC, Boston, Minneapolis, etc. I feel your pain! Today I'm going to try to get to SEATAC to fly back home to the SF Bay Area where it's just raining really hard. :-) I admit I'm a wimpy California girl. I think snow belongs only in the mountains in the winter!
I do hope I make it home though, my mom won't be very happy if I miss her Italian Christmas. (That will be enough guilt to last until next Christmas -- probably longer).
I do have to say though, the snow is beautiful!
I'll try to enjoy! :-)
I've been getting asked a lot lately about how to easily attach a local SQL Server/Express database file (.MDF file) to an instance of SQL Server (any edition). In most of my samples I distribute local SQL Server databases and use user instance connection strings so that if you are running Visual Studio with SQL Express then hitting F5 will auto-attach SQL Express to the database when it runs. This will automatically create the log file (.LDF) as well for you. This "just works" approach works well for people who are using the default install of Visual Studio which installs a SQL Express instance.
However, many developers (including myself) have SQL Server developer edition or higher already installed on our machines or connect to remote development machines with higher editions on them. We want to attach the database file to our instance of SQL Server (by the way you can also attach databases to SQL Express). You can do this easily with sqlcmd as outlined in the MSDN library. Here are the steps:
1. First copy the local database MDF file to the same location as your other databases. This is usually the folder: C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data (or if you are using SQL Express it's probably C:\Program Files\Microsoft SQL Server\MSSQL.SQLEXPRESS\MSSQL\Data )
2. Next open a command prompt and connect to your server using sqlcmd using the syntax -S ServerName\InstanceName. You can use the .\ (dot-backslash) syntax to indicate the local server default instance. In the case of SQL Express the instance is called sqlexpress. So to connect to a local SQL Express database:
C:\>sqlcmd -S .\SQLEXPRESS
Or if we were connecting to our local SQL Server default instance:
C:\>sqlcmd -S .\
Or a named instance (SQLInstance) on another machine (RemoeMachine) it would be:
C:\>sqlcmd -S RemoteMachine\SQLInstance
3. Next you need to switch to the master database (<enter> after each line below):
1> USE Master 2> GO
4. Then you need to enter the following command to indicate the new database name to create and the location of the MDF file. This will attach the database and automatically create a new log file for you (<enter> after each line below):
1> CREATE DATABASE databaseName ON 2> (FILENAME= N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\MDFFileName.MDF') 3> FOR ATTACH; 4> GO
Where databaseName is the name of the database and MDFFileName is the physical name of the MDF file. Notice that we're omitting the log file location so it will create one automatically for you. Now you can change your connection strings in your applications to use this attached database in the application settings. For instance many of my samples use a local database called "OMS.MDF". Instead of the user instance connection string:
Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\OMS.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True
You can change the connection string in all those samples to:
Data Source=.\SQLEXPRESS;Initial Catalog=OMS;Integrated Security=True
It also becomes a lot easier to modify an attached database from the Visual Studio server explorer or from SQL Server Management Studio. Hope that clears it up for folks.
I've played a bit with SmallBasic and blogged about it before -- it's great for anyone just learning how to program. Yesterday Vijaye announced the release of the second version of SmallBasic which includes some improvements that I've been waiting for like removal of conditional parentheses, support for inline comments and some much needed crash fixes. There's also a slew of new library additions to play with.
Check it out here!
We just released a new community article onto the Visual Basic Developer Center by one of our MVPs, Jeff Certain, called Scaling ADO.NET DataTables. In this article Jeff shows shows us how to query and aggregate data using the built in DataTable methods as well as LINQ to DataSets. He compares the performance on indexed and non indexed DataTables in a variety of scenarios. See for yourself what Jeff recommends on large sets of data.
One of the basic things that we need to do as business application developers is to make sure that data being displayed to a user makes sense to them and that they know what type of data something is when they are making edits. In every business application I've written the data entry forms needed to format data in different ways. Let's take a look at how we do this in Windows Presentation Foundation.
IValueConverter
In WPF there is an interface called IValueConverter that you can implement on a class to specify how data should be converted for display in the control as well as a way to convert it back to the data source. Then you reference this class in the XAML on the data binding for each control. For instance, let's say we have a very simple form displaying an order where we want to format the Order Date and Order Total.
We don't want to display the time portion of our date and we'd also like to display the decimal Total in currency format. We also want to make sure users can't type the wrong data types in those fields, i.e. don't allow character strings. The first thing to do is write a simple converter class that will format our controls for display as well as verify the correct data types are entered by the user.
Public Class MyFormatter Implements IValueConverter Public Function Convert(ByVal value As Object, _ ByVal targetType As System.Type, _ ByVal parameter As Object, _ ByVal culture As System.Globalization.CultureInfo) As Object _ Implements System.Windows.Data.IValueConverter.Convert If parameter IsNot Nothing Then Return Format(value, parameter.ToString()) End If Return value End Function Public Function ConvertBack(ByVal value As Object, _ ByVal targetType As System.Type, _ ByVal parameter As Object, _ ByVal culture As System.Globalization.CultureInfo) As Object _ Implements System.Windows.Data.IValueConverter.ConvertBack If targetType Is GetType(Date) OrElse targetType Is GetType(Nullable(Of Date)) Then If IsDate(value) Then Return CDate(value) ElseIf value.ToString() = "" Then Return Nothing Else Return Now() 'invalid type was entered so just give a default. End If ElseIf targetType Is GetType(Decimal) Then If IsNumeric(value) Then Return CDec(value) Else Return 0 End If End If Return value End Function End Class
The Convert method is called when data is coming out of the data source and into the control for display. Here we're taking advantage of the parameter called parameter (very creative name <g>). I'm just using the Visual Basic Format function here for simplicity but you can write any type of formatting code here. The VB Format function takes in simple string format styles to format values and there are a bunch of predefined ones for dates and numbers. You can also specify your own. It's very similar to the String.Format .NET framework method but it is simpler to specify the styles. So to format a date value to only show the date portion we could pass a 'd' as the parameter. Using the predefined masks the Format function is internationally aware. However, also note that you can use the culture parameter to determine the CultureInfo as well.
The ConvertBack method is called when data is going back into the data source and it gives us a chance to take the string values the user enters and convert them to their correct data types. Here I'm checking the targetType in order to determine what the type of the value should be and then attempting to convert it back to the real data type. If the value cannot be converted, say the user typed the character "B" for the date field, then I'm just returning a default value. In the case of my date it allows null values so if the user blanks out the date then the value becomes the empty string and we return Nothing (null).
Specifying the Converter on the Bindings
Next we need to augment the XAML so that we can refer to our converter class in the bindings. What we need to do is add this class as a static resource of the window by first adding an XML namespace to identify our local project and then adding the reference into the Window.Resources:
<Window x:Class="Formatting" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MyProject" Title="Formatting" Height="207" Width="300"> <Window.Resources> <local:MyFormatter x:Key="myformatter" /> </Window.Resources>
Now we can augment the data bindings of the fields we want formatting on by specifying the Converter and ConverterParameter properties on the Binding:
<TextBox Height="28" Width="Auto" Margin="3" IsReadOnly="True" Name="txtID" Text="{Binding Path=OrderId}"/> <TextBox Height="28" Width="Auto" Margin="3" Name="txtProductName" Text="{Binding Path=ProductName}"/> <TextBox Height="28" Width="Auto" Margin="3" Name="txtOrderDate" Text="{Binding Path=OrderDate, Converter={StaticResource myformatter}, ConverterParameter='d'}"/> <TextBox Height="28" Width="Auto" Margin="3" Name="txtOrderTotal" Text="{Binding Path=Total, Converter={StaticResource myformatter}, ConverterParameter='c2'}"/>
Now when we run our form we will see the data displayed properly and you'll also notice that invalid characters that would cause an incompatible data type aren't allowed. We can also be lazy with how we enter dates, for instance if we type '3-1' then it will be converted to 3/1/2008 (current year). This is generally a nice thing to enable for users.
Using String.Format instead of Format
If we don't want to (or can't) use the Format method then we can use the String.Format method instead to display our data by changing our Convert method code (notice that I have to explicitly specify the culture now):
If parameter IsNot Nothing Then Return String.Format(culture, parameter.ToString(), value) End If
However, the style parameter also needs to be changed as well because String.Format requires the styles to be surrounded by curly braces. This doesn't play so nice with the curly braces in the XAML binding so we end up having to escape them:
<TextBox Height="28" Width="Auto" Margin="3" Name="txtOrderDate" Text="{Binding Path=OrderDate, Converter={StaticResource myformatter}, ConverterParameter='\{0:d\}'}"/> <TextBox Height="28" Width="Auto" Margin="3" Name="txtOrderTotal" Text="{Binding Path=Total, Converter={StaticResource myformatter}, ConverterParameter='\{0:c\}'}"/>
Now you know why I like Format better that String.Format :-)
So as you can see it's pretty easy to set up formatting on controls in WPF. Look for the next WPF How Do I video on this coming to a Developer Center near you very soon. :-)
The VB Team just anounced the VB Key Bindings poster for VS 2008. Sweet!! I didn't even know about some of these keyboard short-cuts. Thanks to Lisa on the VB Team for providing these.
Unlike LINQ to SQL, in Visual Studio 2008 Service Pack 1 explicit loading is the default behavior in the Entity Framework. When a query is executed within the Entity Framework, the entities returned by the query are fully accessible, but any associated entities are not immediately loaded. This means that if we have a Master-Detail relationship in our model, say Customer related to many Orders, and we query for a Customer then only the Customer entity will be returned, not the related Orders.
Now LINQ to SQL will load any related entities by default when/if they are accessed, meaning that LINQ to SQL lazily loads the related data by default when it's accessed. The EF team wanted to make this much more explicit. They believe that a developer should always be very aware when data is being fetched and I tend to agree here. All the business applications I have ever written were very careful about how much data was being loaded and how often network/service calls were being made. This is very important to the scalability of your solutions. In any data application you need to always balance the amount of data being returned versus the number of queries you need to make to your database, and that can be very expensive depending how "far" away your database is from the caller.
Implementing lazy loading works well when you only need to make a few additional calls for the related data or the data is optional (like triggered by a user action). On the other hand, if you know you will always need the related data then it is probably more efficient to load the related entities in a single call. This is called eager loading -- there is more data returned to you but there is less chit-chat between the client and the database.
So although you have to be explicit about loading related entities with EF, this gives you the power to decide how to best fit these loading techniques in your applications. And luckily the code is straightforward. Let's take a look.
Creating a Simple Master-Detail Model
In order to illustrate these loading techniques let's create a simple one-to-many example using our favorite database, Northwind. Using Visual Studio 2008 Service Pack 1 I've added a new item to the project and selected Entity Data Model, chose the "Generate from Database" option, and selected Customers and Orders tables from Northwind. So here's my Entity Data Model (EDM):
Setting up Windows Form Data Binding to an EDM
Let's display this data on a Windows Form in two related DataGridViews. You can design the form using the data sources window against the Customer and Order entities in the model, you just need to select Data on the main menu and then Add New Data Source. When the Data Source Configuration wizard opens select Object data source and then select the Customers entity. (BTW, this is exactly how you would do it if using LINQ to SQL classes or your own business objects). The related Orders collection will automatically be pulled in so just select Customers and click Next.
Now you can use your data sources window to design your windows form. Drag the Customers entity as a DataGridView onto a Windows form and then drag the related Orders entity onto the form below the Customers to set up a Master-Detail form. (Sorry if this is a recap for you all but I always get questions on this when I assume people know this! ;-))
Lazy Loading Related Entities
Okay back to the point. First write a query that selects the Customer who's CustomerID is ALFKI. Then we can set the CustomersBindingSource.DataSource property to the query result and it will execute the query on the load of our form.
Public Class Form1 Private db As New NorthwindEntities Private Sub Form1_Load() Handles MyBase.Load Dim query = From c In db.Customers _ Where c.CustomerID = "ALFKI" Me.CustomersBindingSource.DataSource = query.ToList() End Sub End Class
Run the form and you'll see that we are only getting Customer ALFKI, and none of the related Orders. If you do this exact code above with LINQ to SQL classes then it would execute two queries on load and you would see the related Orders. This is because the CustomerBindingSource requests the collection of Customers so it executes the query that we wrote above. When the parent BindingSource's CurrentItem changes when the results are returned then it triggers the child BindingSource to display any related data. With LINQ to SQL this causes an additional query to execute to pick up the children. So as the position moves in the parent, the system is actually hitting the database to get the children in the case of LINQ to SQL.
To do this with EF we can handle the CurrentChanged event of the BindingSource and explicitly load the Orders for that Customers entity:
Private Sub CustomersBindingSource_CurrentChanged() Handles CustomersBindingSource.CurrentChanged Dim c = TryCast(Me.CustomersBindingSource.Current, Customers) If c IsNot Nothing Then If Not c.Orders.IsLoaded Then c.Orders.Load() End If End If End Sub
Now when we run this again you will see the related Orders and two queries will execute against the database.
Eager Loading Entities
But what if we don't want to make two separate queries against the database? In the scenario above we always want to display the related Orders with the Customers so it would be better to make a single call to the database to retrieve the Customer and the Orders. In that case we can use the Include method that is available on an entity and we add this to our query in our form's Load:
Dim query = From c In db.Customers.Include("Orders") _ Where c.CustomerID = "ALFKI"
Now when we run the form again we will see the same results, but this time there is only one query being made against the database. So although EF forces us to think harder about how our data should be loaded, this is a generally good thing for most business application development. It's up to us developers to determine the best technique for our situations.
A member of the developer community, Andreas Håkansson (a.k.a The Code Junkie), is running a series of online interviews with some folks like myself and asking us questions about blogging and why we love it so much. Check out my interview with him here.
I'd also like to thank the many loyal readers of my blog for "listening" to me here online. You are the ones that really make this blog a success. And although I cannot answer all of your hundreds of emails and comments I get here every month, please know that I do read all of them!
Today, December 8th, is the 10 year anniversary of the Italian Visual Basic Tips and Tricks community site.
HAPPY BIRTHDAY to you all and thank you for fostering the Italian Visual Basic community all these years!
Some members of the VB Team created a video, baked a cake, and sang Happy Birthday in Italian in the community's honor. Unfortunately I was speaking in Montreal last week so I couldn't make the video, my apologies! But I want to personally thank the all the people involved in the Visual Basic Tips and Tricks community site.
HAPPY BIRTHDAY!