Friday, August 29, 2008

The two most useful hints for LINQ n00bs.

If you are reading this, welcome to LINQ. You won't regret it. I hope you scoured Scott Guthrie's blog for all the LINQy goodness it has. In terms of keeping your business rules for data together in your app, LINQ is a god send. Defining reams of stored procedures then hooking them all up in ADO.NET was getting tiresome. Especially if your Update parameter changes would not be detected by a Table Adapter reconfigure no matter how many rebuilds and cleans you ran so you had to recreate from scratch and you forgot to note the extra queys first and crap VSS just cacked itself and the other dev just rebuilt his workstation so he doesn't have a copy and OH MY GOD THE URGE TO KILL IS RISING!!! Now, a couple of tips for first timers. To help avoid random homicide. First, what is the data type returned by a LINQ query? Well, given we have a SalesDataAccess namespace with a SalesRecord class sitting in a LINQ data context, we would do this:
Dim query As System.Linq.IQueryable(Of SalesDataAccess.SalesRecord) = From sr In ldsSales.SalesRecords Select Sales
That's it. IQueryable is the one. You've no idea how hard it was to figure that out with just intellisense and google. Or maybe my googling is lame. If your result set is shaped, you'll need to create a Generic.List with the data types of your result set as items. Put your query in parentheses and use .ToList to make it happen.
Dim query AsGeneric.List(Of String, Integer, String) = (From sr In ldsSales.SalesRecords Select Name = Sales.Name, ID = Sales.ID, Store = Sales.StoreName).ToList
Another good tip is how to use the .Where function. Handy if you have to filter your query according to a list of controls that may or may not have filter options selected. After your query, write something like this for each filter option that has a value.
query = query.Where(Function(salerec As SalesDataAccess.SalesRecord) salerec.Company_Id = ddlCompany.SelectedValue)
So what's going on here? In the Where parameter, you actually define a boolean function that rows from the query will be passed into. If the row would return true from the function, it stays. Otherwise it goes. Obviously the parameter in the function is the same type as the rows in your query. Easy when you know how, but I sacrificed a lot of hair to these two nuggets. My cert books cannot come fast enough.

Send any saved Image over HTTP

How to send an image from your DB in a web page with ASP.NET is well documented. You make an aspx page that sends the bytes on page_load via the response object. If you don't know what type of image you are sending, use the below to figure it out and get your response headers right.
Dim stream As System.IO.MemoryStream Dim img As System.Drawing.Bitmap stream = New System.IO.MemoryStream(ImageBytes) img = System.Drawing.Bitmap.FromStream(stream) If ImageBytes.Length > 0 Then Response.ContentType = "image/" & ImageFormat(img.RawFormat) Response.BinaryWrite(ImageBytes) End If Private Function ImageFormat(ByVal format As System.Drawing.Imaging.ImageFormat) As String If format.Equals(System.Drawing.Imaging.ImageFormat.Bmp) Then Return "BMP" End If If format.Equals(System.Drawing.Imaging.ImageFormat.Emf) Then Return "EMF" End If If format.Equals(System.Drawing.Imaging.ImageFormat.Exif) Then Return "EXIF" End If If format.Equals(System.Drawing.Imaging.ImageFormat.Gif) Then Return "GIF" End If If format.Equals(System.Drawing.Imaging.ImageFormat.Icon) Then Return "Icon" End If If format.Equals(System.Drawing.Imaging.ImageFormat.Jpeg) Then Return "JPEG" End If If format.Equals(System.Drawing.Imaging.ImageFormat.MemoryBmp) Then Return "MemoryBMP" End If If format.Equals(System.Drawing.Imaging.ImageFormat.Png) Then Return "PNG" End If If format.Equals(System.Drawing.Imaging.ImageFormat.Tiff) Then Return "TIFF" End If If format.Equals(System.Drawing.Imaging.ImageFormat.Wmf) Then Return "WMF" End If Return "Unknown" End Function
If you want to actually send the Bitmap you derived from the Bytes, that's a whole other kettle of fish. When you stream the Bitmap you'll have to make sure you set the filter settings on it to high. Setting filter settings on all the various image types is quite a juggle. For gifs you'll even need to define octree quantizing at the very least.

Tuesday, August 26, 2008

How to output a query as an Aspose workbook download.

Being an 'on the job'er rather than a 'cetified'er, I'm often tasked with figuring things out by doing them. Now now, stop your wailing and gnashing of teeth. Unlike the usual fly by night programmer I spend a lot of time researching before I do. That means learning things about what I'm using that are extraneous to the job at hand. I do like to get thanked for this. The only way to do that is advertise, so every time I figure these things out I pass them around. It annoys my manager somewhat, but I'll be damned if I'm going to be invisible anymore. So anyway, here's the first thing I figured out that was actually hard. It was my intro to the Response object and .NET streams. How to output a query as an Aspose workbook verbatim as a download. For those of you that don't use Aspose, it is a suite of document editing dll's for ASP.NET. We use it for handling excel files and pdf's etc etc etc. Here's the code.
' Set up a query Dim ta As New SomeTableAdapter Dim results As SomeDataTable = ta.GetData() ' Set up the Response headers to describe the content being delivered Response.Clear() Response.AddHeader("content-disposition", "attachment;filename=" & filename) Response.Charset = "" 'If you want the option to open the Excel file without saving then comment out the line below 'Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.ContentType = "application/vnd.xls" 'Register Aspose Liscence Dim cellslicense As Aspose.Cells.License = New Aspose.Cells.License() cellslicense.SetLicense("Aspose.Total.lic") Dim wb As New Aspose.Cells.Workbook ' Import Query results into the Workbook wb.Worksheets(0).Cells.ImportDataTable(results, True, "A1") ' Save workbook to a memory stream then output the memory stream to the HTTP Response object Dim stream As System.IO.MemoryStream stream = wb.SaveToStream() stream.WriteTo(Response.OutputStream) Response.End()

Tuesday, August 19, 2008

So now I'm a Pro.

Hi, I'm Chris. After a year of .NET learning 'on the job' I think it's time for some real certification. Namely, the MCTS in Visual Studio 2008. So I have begun this blog, to track my progress and get my tech buddies on my back when the dotOmeter isn't rising. I also want somewhere to post the snippets I've discovered over the last year. Those things that someone with training would know but a lagger like me has to figure out. Intellisense is great but it can't read my mind, only my keystrokes. So now, to push on. Wish me luck!