Archive for the ‘General’ Category
Reporting from objects
For the past month or so the Data Dynamics Reports team has been hard at work attacking various performance issues in the product. My goal is to have one of the fastest reporting engines in our class, and we’ve made some great strides in that regard already. We measure the performance by running various standard reports with different size data sets and measure various attributes while we do so.
We have an internal utility that we use which automates this process and spits out a CSV file, each line being a set of 3 runs of a report. We also run the same report through a competing product to give us a baseline, so for each report there are 2 rows of data.
Report,Product,Rows,PeakMem,AvgMem,Render1,Render2,Render3 BasicChart,DDR,1000,47948,41715,2888,160,149 BasicChart,XXX,1000,56164,43809,3365,944,962
While this format is easy to generate, it is harder to consume and make comparisons; for example it isn’t possible to compute the difference between the two products on this one report without first manipulating the data. This is easily done through code; and by using the Object data provider in DDR it is easy to put this manipulated data into a report.
Here is the code I use to render a report to PDF.
private static void ExportToPdf(ReportDefinition reportDefinition, object data, FileInfo outputFile)
{
var runtime = new ReportRuntime(reportDefinition);
runtime.LocateDataSource += (sender, args) => args.Data = data;
var pdf = new PdfRenderingExtension();
var streamProvider = new FileStreamProvider(outputFile.Directory, outputFile.Name);
var settings = new NameValueCollection();
runtime.Render(pdf, streamProvider, settings);
}
Here data is what I’m binding the report’s dataset to. In this particular case I’m passing in a List<PerformanceRecord> or List<ComparisonRecord>. To keep this code generic I didn’t restrict the parameter to IEnumerable because this same code could be used to bind to an ADO.NET DataTable or DataSet as well.
Overall this was an easy project to implement, the only part that was difficult was writing the code to manipulate the CSV data into a usable format.
RIP Windows Calendar…Hello GMinder
Like many others have found out before me, Microsoft has removed Windows Calendar from Windows 7. Instead they’ve created a new client and integrated it with Windows Live Mail…Thats just fine and all, except that I use gmail’s web interface for all of my email (work and personal) and I don’t want another mail client to deal with when all I want is a calendar.
Where is the iCal-like application for Windows? I’m not asking for much:
- Windows-based Reminders – I need to know when its time to leave for an appointment or switch on the Blue Jackets game. Reminders that pop up in a web page are useless because I may not even be looking at that tab in my browser, at my browser, or even have the browser open (its rare but I do sometimes close Chrome out
) - Ability to easily add new appointments from the application
- Ability to see what appointments I have on an arbitrary day as well as a list of appointments for the day, next few days, or week.
Google Calendar would be great, except for item 1 above. That is built into their Google Talk client, and like I do with my many email accounts and Gmail, I use an IM client that supports all of the various IM protocols I use daily (MSN and ICQ for family/friends and GTalk for work).
Fortunately, I managed to stumble across GMinder a free, OSS, notification application for Windows which pulls its data from Google Calendar. I haven’t started using it yet, but I’m hopeful that it will fulfill my (rather basic) needs. People have been reporting that it doesn’t show the new Sports feeds that were recently added to Google Calendar, so it looks like I may need to dig through the source to fix that. I need to keep up on the Blue Jackets after all
Update: As I had somewhat expected, the issue with sports calendars is a ‘feature’ on Google’s part. The calendar doesn’t appear in the list provided by the gcal api and attempting to access it via the ID available on the calendar site results in an error. A simple google search and I found this page (expand sports) which states:
Keep in mind that it’s not possible to sync sports calendars with other calendar applications at this time.
bummer
Foiled!
Alas, my trip to L.A. for Microsoft PDC has been foiled by illness. In my place, will be Jon “Pilgrim”; our director of technical support. Thanks to the PDC crew for allowing us to make this last minute second change.
The irony of the situation is that the only person I had contact with the day I got ill was my barber….and why was I getting my hair cut? So that it looked decent for the show.
I’m a traveling man
I was just sitting here thinking about some email that came in when I realized an interesting coincidence. Each of the past few years, I’ve been visiting cities farther and farther out west for various tech shows.
In Spring of 2007 I visited Denver for Devscovery, at the time the farthest I’d traveled West in the US. In Fall of 2008 I visited Las Vegas for Dev Connections, again the farthest I’ve gone West. Now it’s official, this November I will be going to PDC in LA, and yet again it’ll be the farthest I’ve traveled West.
This only begs the question; who is going to be putting on a show in Alaska or Hawaii next year?
Welcome FarPoint!
Its been a while since my last post. Work on Windy Garden has slowed considerably for a while; mainly because I’ve been working on other things but I did get a lot accomplished on it. I’ll go back to it eventually and post about it here.
But that isn’t why I write this morning; as I wrote almost a year ago I’m now employed by GrapeCity following its acquisition of Data Dynamics. This week, GrapeCity has announced that it has acquired FarPoint, creators of some very impressive controls and good friends to many of us that worked at Data Dynamics. FarPoint Spread, an Excel-compatible .NET spreadsheet component, is a great companion to the line of data analysis and reporting controls already offered by GrapeCity.
ActiveReports 6 Beta, now available!
The ActiveReports team has just released the first public beta for ActiveReports 6!
This new version has many new features in it, with a healthy mix of design-time and run-time enhancements.
My favorite new features are the Flash viewer control, designer snap lines, and RepeatToFill option.
Flash Viewer
The Flash viewer control makes it easy to provide a great looking report viewer on your web page. It replaces the ActiveX control due to the obvious limitations that technology presented users, not to mention the security implications with using ActiveX that kept many people from using it.
Designer Snap Lines
Snap lines make it a cinch to line up the controls in your report. Now table style layouts are easier than ever to create and avoid the issues that overlapping controls can cause when exported to Excel.
Repeat to Fill
Have an Invoice style document that you need to generate, where the report contents fills an area on the page? Repeat to Fill to the rescue! This new property makes it possible to generate green-bar reports that fill the page, even if there isn’t enough data to do it.
Read what Sanjeev had to say about the ActiveReports 6 beta release.
LINQ to SQL quick tip
Quick tip: If you are going to composite method calls together in order to make use of multiple method calls to refine the SQL Query to be generated, make sure the calls are made against IQueryable<T> objects and not IEnumerable<T>.
LINQ method calls (Where, Skip, Take, Count, etc) against IQueryable<T> have different extension methods that get called compared to those that get called when called against an IEnumerable<T> argument.
To illustrate this, consider the following design. I have a model which only does a few things, but to reduce the amount of code duplication I split the query refinements into individual methods. I have a base method which just selects the data from the table. Another method which will perform a Where query on data passed in, another which will Page the data passed in, and another which will just count the number of rows in the data passed in.
In other words, I can do this:
IEnumerable<TEntity> GetSearchResults( string search, int page )
{
IEnumerable<TEntity> results = QueryData();
results = SearchData( results, search );
results = PageData( results, page, Constants.ResultsPerPage );
return results;
}
If these methods take and return IEnumerable<T> bad things start to happen, foremost is that the base query selects everything out of the table. The Where query is all performed client side rather than being generated into the SQL query, and the same for the paging and counting!
Swap out IEnumerable<T> for IQueryable<T> and things begin to work well though. The Where query is generating Where clauses in SQL and the same goes for the other methods. And since IQueryable<T> requires implementers to also implement IEnumerable<T>, at any point in time I can decide to stop chaining calls and revert to IEnumerable<T> so method callers have no idea what the internal implementation of getting that IEnumerable<T> really is.
The only changes I need to make to the code I have above is to change the results variable to IQueryable<T>, as wells as the return type and the parameter type of QueryData, SearchData, and PageData to deal with IQueryable<T>. The return type of the GetSearchResults method doesn’t need to be changed!
Edit: I tried to use the syntax highlighting feature of WordPress provided by a google code project, but it failed miserably on the generics.
Data Dynamics Acquired by GrapeCity
I just finished posting the press release to the Data Dynamics website, Data Dynamics has been acquired by GrapeCity.
The name probably isn’t very familiar to those in the US; however, GrapeCity has been our partner for a while now. They have been responsible for localizing the entire ActiveReports product for consumption in Japan, translating not only the strings in the control but creating documentation, advertisements, and even putting the product on store shelves! Visual Studio Magazine wrote an article on GrapeCity in Feb. 2006 that discusses some of the unique aspects about the company.
For our current and future users, this acquisition won’t change things much. The website will be getting an update, but the products will remain the same.
ActiveReports will still be the #1 report writer available for .NET developers, and we’re still going to release ActiveReports 6 sometime in the first half of next year.
My team is still hard at work on Data Dynamics Reports 2.0, though we may change the name to match the new owner. We’re continually working on improving Data Dynamics Analysis based on the feedback we’ve gotten so far. And we’ve also got a brand new product in the works that I can’t wait to tell everyone about, but that’s for a future post.
Personally, I’m excited to see what the future holds for us.
Data Dynamics phones/email affected by windstorm
Update: Late afternoon – The servers were back up and running this afternoon. Phone-based sales and technical support will resume at 9am EDT Wednesday morning. E-mail and forum technical support have already resumed, and urgent sales e-mails have already been answered.
Update: 3:00pm – Scott just called (and TimP and Pilgrim just msg’d) to let me know that power was back on at the office. The servers may be down for a short time while they switch them back over to regular power.
Update: 12:05pm – Scott has brought in a generator and restored power to the website and databases. Phone and e-mail are still down. Please post all questions to the support forums. Thanks!
Thanks to a comment from Jim, I realized I should at least put this up so that others wondering the same thing can find the answer.
The remnants of hurricane Ike swept through central Ohio Sunday afternoon, knocking out power to many people and businesses in the area, including Data Dynamics. Without power the website and phones are out of service.
Once power is restored the office will again be open and we’ll get the website back online as soon as possible.
Lambda expressions prove their use to me
With the office closed I’ve been working on a research idea for the next version of Data Dynamics Reports.
First a little background: The idea of what is going on here is to take a collection of objects that implement an interface. This interface defines generic attributes about the appearance of the object. Because not all objects support all of the possible appearance options its necessary to have both a property for the appearance and a boolean “Supports” property to indicate whether the first property is usable.
For example, if I have a TextBox and an Image control. Both implement this interface, and certain properties apply to both controls (f.e. Size and BackColor) however there are certain properties that could only apply to some of the controls (f.e. ForeColor on the TextBox and ImageSizing on the Image).
What the code I’m writing needs to do is, first determine whether the object in the collection supports the property being get/set, and if it does support it get/set it. When I was writing the code for this, it became obvious that the only things changing between any two sets of properties was just the name of the property. This made it a prime candidate in my mind for refactoring, but how?
It’s clear that the method needs to accept 2 delegates, the first is a delegate which returns a boolean and takes in the object in the collection (a Predicate<T> in .NET 2.0+). The second is one to do the actual property setting on the object in the collection (an Action<T> in .NET 2.0+).
If I were writing .NET 1.x, I’d have to create a method for each of the properties so I could create a delegate to them, or use reflection…I’m not sure which is worse there. Beginning with .NET 2.0 I could create anonymous methods, but that’s almost as much typing as the .NET 1.x way.
Thankfully I’m using .NET 3.5 for this project, so I can make use of lambda expressions. The result of calling the methods looks like so:
SetAggregateValue( p => p.SupportsForeColor, p => p.ForeColor = value );
As I mentioned before, this allows me to make use of the two delegates, the first a predicate; the second the action. In the corresponding get method, the compiler even takes care of inferring the return type so I don’t need to deal with typing it out, yet again.
A slight concern I have is that it isn’t readily apparent while reading the code that the first parameter is a predicate. Fortunately, this is just a research project and since we target .NET 2.0; I know there no chance this code will make it into the real code base
Just an observation at 3am