Symmetri Developer Blog

August 22, 2009

WPF ClickOnce deployment issues

General, WPF/Silverlight - By Shourov Bhattacharya

So I’ve just deployed my first WPF project via the web using ClickOnce and thought I would share some of the issues that came up. Firstly, the idea behind ClickOnce is great - creating a single web page link that can do the installation of an application and all of its prerequisite software in one go. However, there were a few issues that came up with the publishing using VS2008:

1) the FTP option in the publishing refused to work. I checked the server name and username/password credentials a hundred times, but the publish failed again and again. The error messages aren’t particularly helpful; you really have no way of telling what exactly went wrong. In the end, I decided to publish to a local folder and do the FTP myself. No biggie, but annoying nonetheless.

2) after deploying to a webpage, I decided to check the installation process; I clicked the “Install” button on the generated webpage from a fresh Vista install. After the usual security warnings, the first thing the install did was to install .NET 3.5 SP1. However, it took a really long time - over ten minutes; and the progress bar hardly moved all the time. I am not sure if that is normal, but it seems that I’ll have to make a note of that when deploying to client’s machines; the average user will probably lose hope and lose patience with that kind of wait unless forewarned.

3) next the installation script tried to install the application itself, but I found that it would not install; the error message I got was “The assembly Microsoft.Windows.Design.Extensibility needs to be added to the GAC.” So it seems that there is a required assembly that is not being installed by the ClickOnce process. Checking back in Visual Studio, I noticed that the assembly “Microsoft.WPFToolkit.VisualStudio.Design” was part of the project references; it seemed to me that any library which is specific to Visual Studio should have nothing to do with the deployed application; so I removed and re-published.

4) That got rid of the previous error all right, but now I found that the install complained about missing other assemblies: Microsoft.Data.SqlServerCe.*. My application did indeed use SQL Server Compact Edition 3.5, but it seemed that the install was not checking for it or downloading it.

The issue here is that the project has references to certain assemblies (Microsoft.Data.SqlServerCe.*), but the publishing process does not automatically pick up the prerequisite software associated with those assemblies. The solution is that we must explicitly define those prerequisites. This can be done under Project Properties in Visual Studio under the Publish tab; press the “Prerequisites” button. In my case, I needed to add “SQL Server Compact 3.5″ as a prerequisite to be downloaded by the installation.

August 14, 2009

WPF DataGrid not refreshing?

General, .NET/C#, WPF/Silverlight - By Shourov Bhattacharya

This is an age-old problem, and the latest version of .NET 3.5/WPF has not solved it. I have been working with the WPF DataGrid that comes with the WPF toolkit, and I have found that refreshing the DataGrid’s DataContext was *not* updating the DataGrid’s display in the UI. I had to add a second line of code to call DataGrid.Items.Refresh() to get the DataGrid to update its display:

dg.DataContext = _items;
dg.Items.Refresh();

Simple really, and a problem that is common to other similar components on other platforms too. However, I am not sure I see the justification in not re-rendering the DataGrid when changing the data context automatically. I suppose there might be an argument for separating out the rendering process if it is a high cost operation and giving the developer control over it (which is what the DataGrid.Items.Refresh() method does).

However, I do not see that behaviour as having been properly documented; and in the absence of documentation, I think it is very reasonable for the developer to expect that the grid display is automatically refreshed when the underlying data is changed. The philosophy behind WPF seems to be that data binding should be more flexible and seamless; overall, it is, but I think having to do this kind of old-school “refresh”-ing detracts from that goal.

August 7, 2009

Anonymous types in C#3.0

.NET/C#, WPF/Silverlight - By Shourov Bhattacharya

C# is moving further and further away from its old C/C++ancestry (or should it be Java?). I like some of the innovations in C#3.0, although most of them have been added in response to what other OO languages have been supporting for some time. One philosophical shift seems to be that C# is now less strict with type safety. You can create new objects and leave it to the compiler to create a temporary type at runtime:

backgroundWorker.ReportProgress(recordCount/10000, new {recordCount = recordCount, skipCount = skipCount});

That second parameter in the method call is an anonymous object; kind of like just a container to hold a couple of properties. It’s only needed for this specific call, so we can create it as an anonymous type and use it only in this very limited context. Behind the scenes, I suspect the compiler is create a temporary class { ... } definition.

August 6, 2009

Bulk data import from CSV to SQL Server CE

General, SQL Server, Algorithms, WPF/Silverlight - By Shourov Bhattacharya

SQL Server Compact Edition is a great little product - a free version of SQL Server that can be easily deployed on clients for mobile and desktop applications. However, it does of course lack many of the less essential features of the SQL Server product. One of the things that it does not support is a way to do a bulk import of data into the database - the BULK INSERT T-SQL command is not available.

Currently I’ve got a project in which I need to get large datasets (400,000+ rows) from a CSV file into a SSCE database in the context of a WPF application. Firstly I tried the most conceptually simple (but probably least efficient) method - I read the CSV file line by line and do an INSERT into the SSCE database using the standard ADO.NET Connection and Command objects. But is is slow. Performance on my run-of-the-mill setup here (WinXP SP2 on an average machine) is of the order of 100,000 rows being imported every hour - which means my first data file of half a million records takes almost five hours to import!

[An added complication is that I need to check for duplicates before INSERTing, and that SSCE doesn’t support the IF EXISTS(…) T-SQL construct either - meaning that I have to do an extra query for every record to check for existence of a duplicate before INSERTing.]

What to try next? It seems that there aren’t many options - I can’t find an alternative to using ADO.NET objects in this context, and there seems to be only one way of inserting data. However, there is plenty of scope for streamlining the way the INSERT is done. Watch this space …

UPDATE: Well, massive performance improvement straight away by keeping an open connection instead of creating one each time. I have now got around 3.6 million records being imported in an hour, as compared to 0.1 million before - about 36 times faster! Taking the new Connection() out of the loop was all that was required.

That is, I went from here:

for (...)
{
    // create connection for every query
    using (SqlCeConnection connection = new SqlCeConnection(connectionString))
    {
        string sql = INSERT into TABLE ….;
        SqlCeCommand cmd = new SqlCeCommand(sql, connection);
        cmd.ExecuteNonQuery();
    }
}

To here:

// create connection once
SqlCeConnection connection = new SqlCeConnection(connectionString);
	
// now re-use same connection over and over
for (...)
{
    if (connection.State != System.Data.ConnectionState.Open) connection.Open();
    string sql = INSERT into TABLE ….;
    SqlCeCommand cmd = new SqlCeCommand(sql, connection);
    cmd.ExecuteNonQuery();
}

Very basic optimization of course - programming 101. However, I was surprised by the scale of the performance improvement - I would not have expected the revised code to be one and a half orders of magnitude faster. Is creating a new ADO.NET Connection really such a costly procedure? And what does this mean for the using keyword? The disadvantage of removing the using{...} block now is that I have to add my own code to clean up and close connections in the case of errors to reduce the risk of memory leaks.

I was going to explore more optimization, but this performance is now good enough in the context of this project. A bulk data import facility for SSCE would be nice though. Given that WPF applications run on the desktop a lot of the time, large datasets are going to be feasible to work with, given that there is no need to pull anything over a network for display in a UI grid etc. In that context, the ability to make bulk changes to data is not an unreasonable thing to want. On the other hand, it looks like basic ADO.NET will do the job okay - at least for me!

August 3, 2009

“Flow” layouts in WPF

WPF/Silverlight - By Shourov Bhattacharya

Some time back I wrote a little post comparing Adobe’s Flex and Microsoft’s Silverlight, two competing technologies for delivering the next generation of user experiences via the web inside the browser. At that time I was making my first foray into the world of Rich Internet Application (RIA) development, and I ended up deciding to do my first project with Adobe Flex. It went well, and I have since done a couple of other big(-ish) commercial projects in Flex.

My latest project, though, has given me the chance to now go back and create a desktop application using Windows Presentation Foundation (WPF), which is Microsoft’s new development platform for creating desktop applications - but can also be used to create browser applications which run in IE. I now understand that Silverlight is a “cut-down” version of WPF that is designed to run across all browsers (and compete against Flex). I’m looking forward to seeing how the development experience progresses with my new WPF project, and then compare it to the learning curve that I climbed when learning to develope with Flex.

One thing that I have already noticed is that the default container controls in the WPF GUI toolbox support a “flow”-type layout - meaning that the optimal layout of children inside the container is automatically calculated at runtime, rather than the developer having to specify absolute positioning. This is a real win compared to Flex - I have had to deal with grief trying to implement my own “flow” layout algorithms in Flex because it is not natively supported. I believe, however, that Silverlight only supports absolute positioning - if that’s true, it’s a real shame.

Get free blog up and running in minutes with Blogsome
Theme designed by Janis Joseph