﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>LINQ to Joe</title>
    <description>This is where I will post my thoughts, discoveries, and tribulations as I learn Language INtegrated Query (LINQ).

</description>
    <link>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;BlogId=1</link>
    <language>en-US</language>
    <managingEditor>joe@rattz.com</managingEditor>
    <pubDate>Mon, 06 Sep 2010 20:11:15 GMT</pubDate>
    <lastBuildDate>Mon, 06 Sep 2010 20:11:15 GMT</lastBuildDate>
    <docs>http://backend.userland.com/rss</docs>
    <generator>Blog RSS Generator Version 3.2.0.29758</generator>
    <item>
      <title>Pro LINQ C# 2010 Now Shipping!</title>
      <description>My copies arrived a couple days ago and it is now in stock at Amazon.</description>
      <link>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=65</link>
      <author>joe@rattz.com</author>
      <comments>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=65&amp;#Comments</comments>
      <guid isPermaLink="true">http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=65</guid>
      <pubDate>Thu, 01 Jul 2010 22:42:35 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://linqdev.com/PublicPortal/DesktopModules/Blog/Trackback.aspx?id=65</trackback:ping>
    </item>
    <item>
      <title>Using LINQ To Filter By Object Type and Then Quantify</title>
      <description>&lt;H1&gt;Using LINQ To Filter By Object Type and Then Quantify&lt;/H1&gt;
&lt;P&gt;Every so often I run across a case where LINQ comes in so handy that I just want to post a quick article sharing some particular usage of it.  For this example I was working on a web page that shows user roles and their permissions within my applictation.  Below is a photo showing how the display looked before my added LINQ code.&lt;/P&gt;
&lt;P&gt;&lt;IMG border=0 alt=RoleDefinitions1.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/RoleDefinitions1.jpg" width=411 height=421&gt;&lt;/P&gt;
&lt;P&gt;My web application has other roles not listed in that image.  This is why there are some permissions that none of the listed roles are approved for such as "Allow Access To Site/User/Role Maintenance".  For this page, I wanted to omit any rows from the display where at least one of the roles wasn't approved for it.  After all, these permissions were irrelevant for these roles.  Displaying them would only confuse my users and invite support questions.&lt;/P&gt;
&lt;P&gt;The data is being displayed in an ASP.NET &lt;SPAN class=csharpcode&gt;GridView&lt;/SPAN&gt; that has been bound to a &lt;SPAN class=csharpcode&gt;DataSet&lt;/SPAN&gt;.  To omit the rows, I decided I would filter the &lt;SPAN class=csharpcode&gt;DataSet&lt;/SPAN&gt; prior to assinging the &lt;SPAN class=csharpcode&gt;GridView&lt;/SPAN&gt;'s &lt;SPAN class=csharpcode&gt;DataSource&lt;/SPAN&gt; property and calling its &lt;SPAN class=csharpcode&gt;DataBind&lt;/SPAN&gt; method.  Please notice that the first column of the &lt;SPAN class=csharpcode&gt;GridView&lt;/SPAN&gt; will contain a &lt;SPAN class=csharpcode&gt;string&lt;/SPAN&gt; for the description of the permission and each subsequent column will contain a &lt;SPAN class=csharpcode&gt;bool&lt;/SPAN&gt; specifying if that role is approved for the permission.  One thing not obvious from the image is that the number of roles is driven by the database and is not static.  If I add another role to my application there will be another column added here and I wouldn't want to have to modify this code to accommodate the additional role.&lt;/P&gt;
&lt;P&gt;Below is my code to call the method to filter the &lt;SPAN class=csharpcode&gt;DataSet&lt;/SPAN&gt;.  &lt;SPAN class=csharpcode&gt;GetMyRoleData&lt;/SPAN&gt; is just a dummy method to acquire the needed data and I do not show it in this example.  I then call the &lt;SPAN class=csharpcode&gt;FilterRows&lt;/SPAN&gt; method that will delete all the rows from the &lt;SPAN class=csharpcode&gt;DataSet&lt;/SPAN&gt; for which no role has approval for that row's permission.  I then set the &lt;SPAN class=csharpcode&gt;GridView&lt;/SPAN&gt;'s &lt;SPAN class=csharpcode&gt;DataSource&lt;/SPAN&gt; property and call the &lt;SPAN class=csharpcode&gt;DataBind&lt;/SPAN&gt; method.  Nothing of note so far.&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;DataSet ds = GetMyRoleData();&lt;BR&gt;FilterRows(ds);&lt;BR&gt;RoleComparisonView.DataSource = ds;&lt;BR&gt;RoleComparisonView.DataBind();&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;Next comes my method to actually filter the unwanted rows.  It would have been very easy to enumerate through each row, which I did, and then enumerate through each column of the row.  If every column is set to &lt;SPAN class=csharpcode&gt;false&lt;/SPAN&gt;, delete the row.  Or, if any column is &lt;SPAN class=csharpcode&gt;true&lt;/SPAN&gt;, don't delete the row.  The latter would be more efficient because I could stop checking once the first column had a &lt;SPAN class=csharpcode&gt;true&lt;/SPAN&gt; value.&lt;/P&gt;
&lt;P&gt;But instead of enumerating through each column and checking its value, LINQ can make the code so much simpler.  Why not just use the &lt;SPAN class=csharpcode&gt;Any&lt;/SPAN&gt; operator?  If any of the elements in the row's array of items is &lt;SPAN class=csharpcode&gt;true&lt;/SPAN&gt;, then I don't want to delete the row.  Alternatively, I could use the &lt;SPAN class=csharpcode&gt;All&lt;/SPAN&gt; operator and make sure they are all set to &lt;SPAN class=csharpcode&gt;false&lt;/SPAN&gt;, but again, this would be less efficient and require every item to be checked.  Using the &lt;SPAN class=csharpcode&gt;Any&lt;/SPAN&gt; operator instead of the &lt;SPAN class=csharpcode&gt;All&lt;/SPAN&gt; operator allows the code to stop once an item is &lt;SPAN class=csharpcode&gt;true&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;There is one last complication and that is the fact that the first column of each &lt;SPAN class=csharpcode&gt;DataRow&lt;/SPAN&gt; is a &lt;SPAN class=csharpcode&gt;string&lt;/SPAN&gt; for the permission description and not a &lt;SPAN class=csharpcode&gt;bool&lt;/SPAN&gt; for a role.  This can easily be overcome though with the &lt;SPAN class=csharpcode&gt;OfType&lt;/SPAN&gt; operator.  Just call the &lt;SPAN class=csharpcode&gt;OfType&lt;/SPAN&gt; operator on the array of items, &lt;SPAN class=csharpcode&gt;ItemArray&lt;/SPAN&gt;, and specify to only return elements of type &lt;SPAN class=csharpcode&gt;bool&lt;/SPAN&gt;.  It's just that simple.  Here is the code.&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;private void FilterRows(DataSet ds)&lt;BR&gt;{&lt;BR&gt;    bool someRoleHasPermission;&lt;BR&gt;    foreach (DataRow dr in ds.Tables[0].Rows)&lt;BR&gt;    {&lt;BR&gt;        someRoleHasPermission = dr.ItemArray.OfType&lt;bool&gt;().Any(b =&gt; b == true);&lt;BR&gt;        if (!someRoleHasPermission)&lt;BR&gt;        {&lt;BR&gt;            dr.Delete();&lt;BR&gt;        }&lt;BR&gt;    }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;So, I enumerate through each &lt;SPAN class=csharpcode&gt;DataRow&lt;/SPAN&gt; in the &lt;SPAN class=csharpcode&gt;DataTable&lt;/SPAN&gt;'s &lt;SPAN class=csharpcode&gt;Rows&lt;/SPAN&gt; collection.  I then call the &lt;SPAN class=csharpcode&gt;OfType&lt;/SPAN&gt; operator on the row's &lt;SPAN class=csharpcode&gt;ItemArray&lt;/SPAN&gt; to return only those items that are a &lt;SPAN class=csharpcode&gt;bool&lt;/SPAN&gt;.  Last I call the &lt;SPAN class=csharpcode&gt;Any&lt;/SPAN&gt; operator and provide a lambda expression returning &lt;SPAN class=csharpcode&gt;true&lt;/SPAN&gt; if any of the items is set to &lt;SPAN class=csharpcode&gt;true&lt;/SPAN&gt;.  Very simple.  I then call the &lt;SPAN class=csharpcode&gt;DataRow&lt;/SPAN&gt;'s &lt;SPAN class=csharpcode&gt;Delete&lt;/SPAN&gt; method if I got a &lt;SPAN class=csharpcode&gt;false&lt;/SPAN&gt; back from the LINQ query.  Just like that, my permissions have been filtered.  Here is one last image showing the &lt;SPAN class=csharpcode&gt;GridView&lt;/SPAN&gt; after calling the &lt;SPAN class=csharpcode&gt;FilterRows&lt;/SPAN&gt; method:&lt;/P&gt;
&lt;P&gt;&lt;IMG border=0 alt=RoleDefinitions2.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/RoleDefinitions2.jpg" width=411 height=346&gt;&lt;/P&gt;
&lt;P&gt;As you can see, LINQ can make so many chores just that much more simple.&lt;BR&gt;&lt;/P&gt;&lt;A style="DISPLAY: none" href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=717226" rel=tag&gt;CodeProject&lt;/A&gt;</description>
      <link>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=63</link>
      <author>joe@rattz.com</author>
      <comments>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=63&amp;#Comments</comments>
      <guid isPermaLink="true">http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=63</guid>
      <pubDate>Mon, 12 Apr 2010 21:48:28 GMT</pubDate>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://linqdev.com/PublicPortal/DesktopModules/Blog/Trackback.aspx?id=63</trackback:ping>
    </item>
    <item>
      <title>Using LINQ With System.Web.Caching.Cache (A Legacy Collection)</title>
      <description>&lt;P&gt; &lt;/P&gt;
&lt;H1&gt;Using LINQ With System.Web.Caching.Cache (A Legacy Collection)&lt;/H1&gt;
&lt;P&gt;&lt;BR&gt;In my previous blog post titled &lt;A HREF="http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=54"&gt;"Creating A Reusable AdRotator ASP.NET User Control Using LINQ"&lt;/A&gt; I took advantage of caching with the &lt;SPAN class=csharpcode&gt;System.Web.Caching.Cache&lt;/SPAN&gt; object to prevent constantly querying the database for the ad content.  Since I intentionally didn't leverage the cache dependencies feature, my cached ad content would only refresh at a certain time interval.  After putting that code into production I realized what I really wanted was a way to manually flush the cache of the ad content when I wanted to.  This would allow me to keep the ad content cached for a long period of time but provided a way to flush the ad content when I wanted it to change.&lt;/P&gt;
&lt;P&gt;So I created a page to allow me to delete just the cached objects that I wanted to.  I did have one small complication though.  I use a third party weather control and it uses the cache too for caching the weather data for each zip code for which it is displayed.  In my production environment, it would not be unusual for there to possibly be several hundred cached weather data objects.  Therefore, on my cache maintenance page, I wanted to filter those out, but provide a way to see them, and delete them, if I chose to.&lt;/P&gt;
&lt;P&gt;I used the ASP.NET &lt;SPAN class=csharpcode&gt;CheckBoxList&lt;/SPAN&gt; server control on the page.  This way I could check the ones I wanted to delete from the cache and press a delete button.&lt;/P&gt;
&lt;P&gt;LINQ became very handy for controlling which cached objects I displayed, as well as programmatically checking them when the Select All checkbox was checked.  Here is the basic user interface:&lt;/P&gt;
&lt;P&gt;&lt;IMG border=0 alt=CacheObjects1.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/CacheObjects1.jpg" width=986 height=190&gt;&lt;/P&gt;
&lt;P&gt;The Display Weather Objects? and Select All checkboxes are just regular checkboxes that autopost to the server when clicked.  The checkboxes under the Select All checkbox are from the &lt;SPAN class=csharpcode&gt;CheckBoxList&lt;/SPAN&gt; and there is one checkbox for each &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; object, except those from the weather server control.&lt;/P&gt;
&lt;P&gt;I took advantage of LINQ to filter out the weather cache objects like this:&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;if (DisplayWeather.Checked)&lt;BR&gt;{&lt;BR&gt;    CacheObjectList.DataSource = Cache.Cast&lt;DictionaryEntry&gt;().OrderBy(i =&gt; i.Key);&lt;BR&gt;}&lt;BR&gt;else&lt;BR&gt;{&lt;BR&gt;    CacheObjectList.DataSource = Cache.Cast&lt;DictionaryEntry&gt;().Where(i =&gt; !i.Key.ToString().StartsWith(WeatherId)).OrderBy(i =&gt; i.Key);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;CacheObjectList.DataTextField = "Key";&lt;BR&gt;CacheObjectList.DataBind();&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;If the DisplayWeather checkbox, the one labeled Display Weather Objects?, is checked, I simply use the &lt;SPAN class=csharpcode&gt;OrderBy&lt;/SPAN&gt; standard query operator to order the objects alphabetically by their key.  Notice though that since the &lt;SPAN class=csharpcode&gt;System.Web.Caching.Cache&lt;/SPAN&gt; objct does not implement &lt;SPAN class=csharpcode&gt;IEnumerable&lt;T&gt;&lt;/SPAN&gt; (and is therefore what I call a legacy collection), I can't call the &lt;SPAN class=csharpcode&gt;OrderBy&lt;/SPAN&gt; standard query operator on it directly.  I must first call either the &lt;SPAN class=csharpcode&gt;Cast&lt;/SPAN&gt; or &lt;SPAN class=csharpcode&gt;OfType&lt;/SPAN&gt; operator first and specify the type of object in its collection, which in this case is &lt;SPAN class=csharpcode&gt;DictionaryEntry&lt;/SPAN&gt;.  The &lt;SPAN class=csharpcode&gt;Cast&lt;/SPAN&gt; (or &lt;SPAN class=csharpcode&gt;OfType&lt;/SPAN&gt;) operator will return an &lt;SPAN class=csharpcode&gt;IEnumerable&lt;T&gt;&lt;/SPAN&gt; (actually an &lt;SPAN class=csharpcode&gt;IEnumerable&lt;DictionaryEntry&gt;&lt;/SPAN&gt; in this case) that I can call the &lt;SPAN class=csharpcode&gt;OrderBy&lt;/SPAN&gt; operator on.&lt;/P&gt;
&lt;P&gt;If the DisplayWeather checkbox is not checked, after calling the &lt;SPAN class=csharpcode&gt;Cast&lt;/SPAN&gt; operator, I then call the &lt;SPAN class=csharpcode&gt;Where&lt;/SPAN&gt; operator to return only those objects in the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; whose key does not start with "WeatherDS:" which I have stored in the variable named &lt;SPAN class=csharpcode&gt;weatherId&lt;/SPAN&gt;.  I use a variable for this string just to make sure I use it consistently throughout the code.  Then, I order the objects again alphabetically.  This allows me to filter out the weather control related &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; objects.  Very nice.&lt;/P&gt;
&lt;P&gt;Here is another screenshot showing the display if the Display Weather Objects? checkbox is checked:&lt;/P&gt;
&lt;P&gt;&lt;IMG border=0 alt=CacheObjects2.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/CacheObjects2.jpg" width=987 height=266&gt;&lt;/P&gt;
&lt;P&gt;Notice that in that image, I have a new checkbox labeled Select All Weather.  This allows me to easily select just the weather checkboxes if I choose.  I also use LINQ when the Select All Weather checkbox is changed:&lt;/P&gt;
&lt;P&gt;&lt;SPAN class=csharpcode&gt;protected void AllWeather_CheckedChanged(object sender, EventArgs e)&lt;BR&gt;{&lt;BR&gt;    foreach (ListItem li in CacheObjectList.Items.Cast&lt;ListItem&gt;().Where(i =&gt; i.Text.StartsWith(WeatherId)))&lt;BR&gt;    {&lt;BR&gt;        li.Selected = AllWeather.Checked;&lt;BR&gt;    }&lt;BR&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Above I use LINQ to only enumerate through those cache objects whose &lt;SPAN class=csharpcode&gt;Text&lt;/SPAN&gt; starts with my weather string.&lt;/P&gt;
&lt;P&gt;But wait, there's more!  What about when the Delete button is pressed?  I also use LINQ to only enumerate through those checkboxes that have been selected:&lt;/P&gt;
&lt;P&gt;&lt;SPAN class=csharpcode&gt;foreach (ListItem li in CacheObjectList.Items.Cast&lt;ListItem&gt;().Where(i =&gt; i.Selected))&lt;BR&gt;{&lt;BR&gt;    Cache.Remove(li.Text);&lt;BR&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;In the first paragraph of my book I ask, "Did you just feel &lt;EM&gt;your&lt;/EM&gt; world shift?"  I hope that by showing how useful LINQ can be, you can now understand why I ask.&lt;/P&gt;
&lt;P&gt;For those interested in the third party ASP.NET weather server control, you can find out more about Milan Negovan's weather control here:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.aspnetresources.com/articles/weather_server_control.aspx" target=_blank&gt;http://www.aspnetresources.com/articles/weather_server_control.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;and here:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.aspnetresources.com/blog/weather_control_1_7.aspx" target=_blank&gt;http://www.aspnetresources.com/blog/weather_control_1_7.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt; &lt;/P&gt;</description>
      <link>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=58</link>
      <author>joe@rattz.com</author>
      <comments>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=58&amp;#Comments</comments>
      <guid isPermaLink="true">http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=58</guid>
      <pubDate>Wed, 03 Mar 2010 22:49:05 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://linqdev.com/PublicPortal/DesktopModules/Blog/Trackback.aspx?id=58</trackback:ping>
    </item>
    <item>
      <title>Creating A Reusable AdRotator ASP.NET User Control Using LINQ</title>
      <description>&lt;BR&gt;
&lt;H1&gt;Creating A Reusable AdRotator ASP.NET User Control Using LINQ&lt;/H1&gt;
&lt;P&gt;I recently had the need for an AdRotator on one of my websites.  ASP.NET already comes with an AdRotator server control but since I wanted to make it even easier to reuse, I decided to create an ASP.NET user control that leverages the ASP.NET AdRotator server control, but handles all the lower-level details.&lt;BR&gt;&lt;/P&gt;
&lt;H2&gt;Requirements&lt;/H2&gt;
&lt;P&gt;One of my requirements is that I wanted to be able to have multiple instances of this user control, perhaps even on the same page.  I also wanted to be able to either have an instance have its own pool of ad content, or share the ad content with another instance.  Since the built-in AdRotator control has a Keyword feature, that would be how I would control which pool of ad content an instance of the user control displayed content from.&lt;/P&gt;
&lt;P&gt;Additionally, I wanted the ad content coming from the database, as opposed to a configuration (XML) file, which the built-in AdRotator server control allows as of ASP.NET 2.0.  This way I could add new content right into the database.&lt;/P&gt;
&lt;P&gt;Another requirement was that I didn't want the AdRotator hitting the database every time the page was refreshed.  For this, I planned to use the Cache object that exists in ASP.NET.&lt;/P&gt;
&lt;P&gt;Another requirement was that I wanted the ability to be able to temporarily disable an ad without having to remove it from the database, and I wanted to be able to provide effective and expiration dates for an ad so that they could come online and go offline automatically as scheduled.&lt;/P&gt;
&lt;P&gt;My last requirement was that I wanted to use LINQ to SQL for the database access.&lt;/P&gt;
&lt;P&gt;Creating an AdRotator user control using the built-in AdRotator server control and LINQ made this all fairly trivial to accomplish.  Here is how I did it.&lt;/P&gt;
&lt;H2&gt;Creating the LINQ to SQL DBML File&lt;/H2&gt;
&lt;P&gt;First, lets start with my data model.  Here is what my SQL Server database table looked like:&lt;/P&gt;
&lt;P&gt;&lt;IMG border=0 alt=AdRotatorContentLayout.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/AdRotatorContentLayout.jpg" width=341 height=201&gt;&lt;/P&gt;
&lt;P&gt;As you can see, I have all the fields needed for an ad including an image URL, navigation URL, keyword, enabled, effective date, and expiration date.&lt;/P&gt;
&lt;P&gt;Next, in Visual Studio 2008, I created a LINQ to SQL DBML file for my AdRotatorContent table.  To do this, right-click on your Project in the Solution Explorer window and select the Add | New Item menu.  Select the LINQ to SQL Classes template and give the new item the name of your database.  In this example, I will use Storefront for the name of my new item.  This will create a file named Storefront.dbml in my project.  This also means that I will have a derived DataContext class named StorefrontDataContext that I will use to access the database with LINQ to SQL.&lt;/P&gt;
&lt;P&gt;&lt;IMG border=0 alt=StorefrontDBMLDesigner.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/StorefrontDBMLDesigner.jpg" width=788 height=383&gt;&lt;/P&gt;
&lt;P&gt;Once the desginer canvas window is open, find your database in the tree of Data Connections in the Server Explorer window.  You may need to add a connection to your database by right-clicking on the Data Connections node and selecting the Add Connection menu item.  Once you have located (or created) your database in the Data Connections node, expand the Tables node.  Drag the AdRotatorContent table node into the designer canvas as seen in the image above.  Save your DBML file.  This will allow you to access the AdRotatorContent table with your derived DataContext class, StorefrontDataContext in my case, using LINQ to SQL.&lt;BR&gt;&lt;/P&gt;
&lt;H2&gt;Creating the AdRotatorControl User Control&lt;/H2&gt;
&lt;P&gt;Next, I need to create the user control.  I will name it AdRotatorControl.  Here is the markup in the AdRotatorControl.ascx file:&lt;/P&gt;
&lt;P&gt;&lt;SPAN class=csharpcode&gt;&lt;%@ Control Language="C#" AutoEventWireup="true" CodeBehind="AdRotatorControl.ascx.cs" Inherits="GPCStoreFront.UserControls.AdRotatorControl" %&gt;&lt;BR&gt;&lt;?xml:namespace prefix = asp /&gt;&lt;asp:AdRotator id=AdRotator1 runat="server" ImageUrlField="ImageUrl" AlternateTextField="AlternateText" NavigateUrlField="NavigateUrl"&gt;&lt;/asp:AdRotator&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;That's all there is to the markup.  This is really trivial so far.  I simply set the NavigateUrlField, AlternateTextField, and ImageUrlField properties to the names of the columns in the database where those values will come from.&lt;/P&gt;
&lt;P&gt;Now let's take a look at the code-behind in the AdRotatorControl.ascx.cs file:&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;using System;&lt;BR&gt;using System.Collections.Generic;&lt;BR&gt;using System.Data.SqlClient;&lt;BR&gt;using System.Linq;&lt;BR&gt;using System.Web;&lt;BR&gt;using System.Web.UI;&lt;BR&gt;using System.Web.UI.WebControls;&lt;/P&gt;
&lt;P&gt;namespace &lt;FONT color=#ff0000&gt;[YOUR NAMESPACE GOES HERE]&lt;/FONT&gt;&lt;YOUR NAMESPACE GOES HERE&gt;&lt;BR&gt;{&lt;BR&gt;    public partial class AdRotatorControl : System.Web.UI.UserControl&lt;BR&gt;    {&lt;BR&gt;        public string Keyword { get; set; }&lt;BR&gt;        public string Target { get; set; }&lt;BR&gt;        public string CacheName { get { return String.Format("AdContent-{0}", Keyword); } }&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;Please notice that you will need to update the namespace with your namespace.  Notice that I have added a &lt;SPAN class=csharpcode&gt;using&lt;/SPAN&gt; directive for the &lt;SPAN class=csharpcode&gt;System.Data.SqlClient&lt;/SPAN&gt; namespace since I will be using LINQ to SQL.&lt;/P&gt;
&lt;P&gt;The only other significance of the code so far is that I have added three public properties: &lt;SPAN class=csharpcode&gt;Keyword&lt;/SPAN&gt;, &lt;SPAN class=csharpcode&gt;Target&lt;/SPAN&gt;, and &lt;SPAN class=csharpcode&gt;CacheName&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;I will use the &lt;SPAN class=csharpcode&gt;Keyword&lt;/SPAN&gt; property as a filter on the records from the AdRotatorContent table Keyword column.  This is what will allow me to have multiple instances of the AdRotatorControl user control that either share the ad content or have independent content.  I have made this a public property so that I can set the property in the markup for the AdRotatorControl user control.  This will allow me to add the user control to a page without adding any code to the page to configure the user control.&lt;/P&gt;
&lt;P&gt;I will use the &lt;SPAN class=csharpcode&gt;Target&lt;/SPAN&gt; property merely as a passthrough to set the AdRotator server control's &lt;SPAN class=csharpcode&gt;Target&lt;/SPAN&gt; property.  This will dictate where the navigation URL will be loaded when the ad image is clicked.  Use &lt;SPAN class=csharpcode&gt;_blank&lt;/SPAN&gt; to cause the URL to be opened in a new browser window.  Use &lt;SPAN class=csharpcode&gt;_self&lt;/SPAN&gt; to open the URL in the current browser window.  Of course you can use any valid target, but those are the standard ones that make the most sense.  In my case, I will always use &lt;SPAN class=csharpcode&gt;_blank&lt;/SPAN&gt; because it is one of my self imposed web developement rules that no link should ever navigate away from your own site.  This is also a public property so that it can be set in the markup thereby preventing the requirement of adding code.&lt;/P&gt;
&lt;P&gt;I will use the &lt;SPAN class=csharpcode&gt;CacheName&lt;/SPAN&gt; property to retrieve the key name I will use to store and retrieve the ad content data from the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt;.  Please notice that this property is a read-only property as there is no &lt;SPAN class=csharpcode&gt;set&lt;/SPAN&gt; statement.  I wanted a property for the key name to make sure it was used consistently through the code.  Also please notice that the key name is dependent on the &lt;SPAN class=csharpcode&gt;Keyword&lt;/SPAN&gt; property thereby establishing it's uniqueness in the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt;.  You may want to make this property private, but I made it public just in case I want to access it from outside the class for debugging purposes.&lt;/P&gt;
&lt;P&gt;Next, let's take a look at the &lt;SPAN class=csharpcode&gt;Page_Load&lt;/SPAN&gt; method:&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;        protected void Page_Load(object sender, EventArgs e)&lt;BR&gt;        {&lt;BR&gt;            this.AdRotator1.Target = Target;&lt;/P&gt;
&lt;P&gt;            AdRotatorContent[] data = GetAdData();&lt;BR&gt;            this.AdRotator1.DataSource = data;&lt;BR&gt;            this.AdRotator1.DataBind();&lt;BR&gt;            this.Visible = data.Length &gt; 0;&lt;BR&gt;        }&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;First, please notice that I am setting the AdRotator server control's &lt;SPAN class=csharpcode&gt;Target&lt;/SPAN&gt; property based on the user control's &lt;SPAN class=csharpcode&gt;Target&lt;/SPAN&gt; property.  This is what I meant earlier when I said I was using it as a passthrough.  Its sole purpose is to allow the AdRotator server control's &lt;SPAN class=csharpcode&gt;Target&lt;/SPAN&gt; property to be set from the user control's markup preventing the need to actually write any code to add an instance of the user control to a page.&lt;/P&gt;
&lt;P&gt;Next I call the &lt;SPAN class=csharpcode&gt;GetAdData&lt;/SPAN&gt; mefhod.  This is where all the real work will be done as well as caching.  For now, we'll just assume it returns an array of ad content matching the &lt;SPAN class=csharpcode&gt;Keyword&lt;/SPAN&gt; specified in the user control's markup regardless of whether that data comes from the database or cache.&lt;/P&gt;
&lt;P&gt;Then I simply bind the AdRotator server control to the array of ad content data and set the visibility of the user control depending on whether there is any ad content.  This allows the user control to simply disappear if no ads exist for the specified &lt;SPAN class=csharpcode&gt;Keyword&lt;/SPAN&gt; that are enabled and valid for the current date and time.&lt;/P&gt;
&lt;P&gt;Now let's take a look at the &lt;SPAN class=csharpcode&gt;GetAdData&lt;/SPAN&gt; method:&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;        private AdRotatorContent[] GetAdData()&lt;BR&gt;        {&lt;BR&gt;            //  Attempt to retrieve the ad content data from the cache.&lt;BR&gt;            AdRotatorContent[] data = Cache[CacheName] as AdRotatorContent[];&lt;BR&gt;            if (data == null)&lt;BR&gt;            {&lt;BR&gt;                using (StorefrontDataContext dc = new StorefrontDataContext())&lt;BR&gt;                {&lt;BR&gt;                    DateTime now = DateTime.Now;&lt;BR&gt;                    data = dc.AdRotatorContents&lt;BR&gt;                        .Where(arc =&gt; arc.Keyword.Equals(Keyword) &amp;&amp; arc.Enabled == true &amp;&amp; &lt;BR&gt;                                     arc.EffectiveDate &lt;= now &amp;&amp; arc.ExpirationDate &gt;= now)&lt;BR&gt;                        .ToArray();&lt;BR&gt;                    Cache.Insert(CacheName, data, null, DateTime.Now.AddMinutes(5), TimeSpan.Zero,&lt;BR&gt;                        System.Web.Caching.CacheItemPriority.NotRemovable, null);&lt;BR&gt;                }&lt;BR&gt;            }&lt;BR&gt;            return data;&lt;BR&gt;        }&lt;BR&gt;&lt;FONT size=2&gt;    }&lt;BR&gt;}&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN class=csharpcode&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;I am hoping you are blown away by how trival this method turned out to be.  First, I attempt to retrieve the ad content array from the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; using the &lt;SPAN class=csharpcode&gt;CacheName&lt;/SPAN&gt; property I described earlier.  Next, I check to see if it is &lt;SPAN class=csharpcode&gt;null&lt;/SPAN&gt;.  If it is not &lt;SPAN class=csharpcode&gt;null&lt;/SPAN&gt;, I merely need to return the &lt;SPAN class=csharpcode&gt;AdRotatorContent&lt;/SPAN&gt; array.  If it is &lt;SPAN class=csharpcode&gt;null&lt;/SPAN&gt;, meaning it is not in the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt;, I instantiate a &lt;SPAN class=csharpcode&gt;StorefrontDataContext&lt;/SPAN&gt;.  This is my LINQ to SQL derived &lt;SPAN class=csharpcode&gt;DataContext&lt;/SPAN&gt; class.  Notice that I am taking advantage of the &lt;SPAN class=csharpcode&gt;using&lt;/SPAN&gt; statement to automatically handle disposing the object when I am finished with it.&lt;/P&gt;
&lt;P&gt;Next, I simply store the current time in a variable since I will reference it in more than one spot, just to ensure consistency of it.&lt;/P&gt;
&lt;P&gt;Then I make my LINQ to SQL query.  Notice that I am using the &lt;SPAN class=csharpcode&gt;Where&lt;/SPAN&gt; operator to retrieve only those ads for the specified &lt;SPAN class=csharpcode&gt;Keyword&lt;/SPAN&gt; that are enabled and whose effective and expiration dates make the ad valid now.  Also please notice that I am calling the &lt;SPAN class=csharpcode&gt;ToArray&lt;/SPAN&gt; method to convert the returned &lt;SPAN class=csharpcode&gt;IQueryable&lt;ADROTATORCONTENT&gt;&lt;/SPAN&gt; to an array.  This is to prevent deferred query execution and the query executing later, after I have disposed of the &lt;SPAN class=csharpcode&gt;StorefrontDataContext&lt;/SPAN&gt;.  Despite discussing deferred query execution at great length in my book, Pro LINQ: Language Integrated Query in C# 2008, even I forgot to be mindful of it, and this initially bit me.  The most important part though is recognizing it when it happens and knowing how to resolve the problem.  For this case, I decided to use the &lt;SPAN class=csharpcode&gt;ToArray&lt;/SPAN&gt; method to create an array from the &lt;SPAN class=csharpcode&gt;IQueryable&lt;ADROTATORCONTENT&gt;&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;Next, I am inserting the array of ad content into the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; using the &lt;SPAN class=csharpcode&gt;CacheName&lt;/SPAN&gt; property, again to ensure consistency between the insert here, and the retrieval at the beginning of the method.  I am also specifying for the data to live in the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; for 5 minutes.  This means that the data will be cached for 5 minutes and then deleted from the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt;.  When the next query arrives after the deletion, the code will cause the database to be queried and the data will be stored in the cache again where it will live for another 5 minutes.  I used 5 minutes for this example because it is simple and makes testing the caching, disabling of ads, and effective and expiration dating of ads easier.  You may want a longer time in production.  In my real code, I will set this longer and store the time period in a configuration setting for the web application.&lt;/P&gt;
&lt;P&gt;There are other, more sophistocated, ways to expire this data from the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt;, but for this purpose, a time limit is sufficient.  You should be aware though that you can create &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; dependencies that will detect if a file or database table (among other things) is changed and delete the object from the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; when that happens.  So in fact, we could have created a database table dependency on the AdRotatorContent table itself so that when it is changed, the ad content is deleted from the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; and then read again from the database.  For a really important real-time system, that would be ideal.  However, the way you do this is dependent on the database and its version so this is beyond the scope of this blog post.  And, for most people's ad content, having such real-time access to the ads is not necessary.  I expect Google would feel differently though.  ;-)  For more information about creating &lt;SPAN class=csharpcode&gt;Cache &lt;/SPAN&gt;dependencies or the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; object in general, Matthew MacDonald's &lt;A href="http://www.amazon.com/Pro-ASP-NET-2008-Second-Windows-Net/dp/1590598938/ref=ntt_at_ep_dpi_9?tag=netsplore-20" target=_blank&gt;Pro ASP.NET 3.5 in C# 2008 (ISBN 1-59059-893-8)&lt;/A&gt; is a good read and I refer to it often.&lt;/P&gt;
&lt;P&gt;Also notice that I am specifying a &lt;SPAN class=csharpcode&gt;CacheItemPriority&lt;/SPAN&gt; of &lt;SPAN class=csharpcode&gt;NotRemovable&lt;/SPAN&gt;.  This is because I found that the caching on my production server didn't behave as I would expect.  Despite having plenty of memory available, my &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; objects were getting flushed prior to their expiration time, and almost immediately.  You can read more about this here:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.west-wind.com/Weblog/ShowPost.aspx?id=11379" target=_blank&gt;http://www.west-wind.com/Weblog/ShowPost.aspx?id=11379&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;The last argument to the &lt;SPAN class=csharpcode&gt;Insert&lt;/SPAN&gt; method is a callback handler for when items get flushed from the cache.  I have specified this to be &lt;SPAN class=csharpcode&gt;null&lt;/SPAN&gt; since I don't want a callback handler.  This can however be a useful feature to determine why your &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; objects are getting flushed.&lt;BR&gt;&lt;/P&gt;
&lt;H2&gt;Adding the AdRotatorControl User Control To a Page&lt;/H2&gt;
&lt;P&gt;All that's left is to add the user control to a page.  Here is the markup to do that:&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;&lt;?xml:namespace prefix = uc2 /&gt;&lt;uc2:AdRotatorControl id=AdRotatorControl1 runat="server" Target="_blank" Keyword="Login"&gt;&lt;/uc2:AdRotatorControl&gt;&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;Please notice that I am specifying the &lt;SPAN class=csharpcode&gt;Keyword&lt;/SPAN&gt; and &lt;SPAN class=csharpcode&gt;Target&lt;/SPAN&gt; properties.  The &lt;SPAN class=csharpcode&gt;Keyword&lt;/SPAN&gt; will be used to filter just those ads in the database matching the &lt;SPAN class=csharpcode&gt;Keyword&lt;/SPAN&gt; specified in this property.  This would allow me to put more than one instance of the user control on a single page but to have a different pool of ad content.  For example, I might put one instance of the user control on the page and specify the &lt;SPAN class=csharpcode&gt;Keyword &lt;/SPAN&gt;as "Tech" to pull just those ads from the database having the Tech keyword.  I might add another instance of the user control on the same page and specify the &lt;SPAN class=csharpcode&gt;Keyword &lt;/SPAN&gt;as "Political" to pull just the political ads.  I could even add an instance of the user control to another page and specify the "Tech" or "Political" &lt;SPAN class=csharpcode&gt;Keyword&lt;/SPAN&gt; so that it would share the same pool of ad content.&lt;/P&gt;
&lt;P&gt;Here are a couple screenshots of the AdRotatorControl user control in action:&lt;/P&gt;
&lt;P&gt;&lt;IMG border=0 alt=AdRotatorInAction1.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/AdRotatorInAction1.jpg" width=599 height=182&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG border=0 alt=AdRotatorInAction2.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/AdRotatorInAction2.jpg" width=599 height=182&gt;&lt;/P&gt;
&lt;H2&gt;&lt;BR&gt;Using ADO.NET Instead of LINQ to SQL&lt;/H2&gt;
&lt;P&gt;While it was one of my requirements to use LINQ to SQL, nothing says that you must.  Should you prefer to use ADO.NET rather than LINQ to SQL, simply replace the LINQ to SQL code with ADO.NET code retrieving a &lt;SPAN class=csharpcode&gt;DataSet&lt;/SPAN&gt; from the database and store that &lt;SPAN class=csharpcode&gt;DataSet&lt;/SPAN&gt; in the &lt;SPAN class=csharpcode&gt;Cache&lt;/SPAN&gt; object instead of the array.  This is a very trivial change to make.&lt;/P&gt;
&lt;P&gt;All in all, I am very pleased with the way this AdRotatorControl turned out.  I think you will find it fairly useful and simple to add to your web application.&lt;/P&gt;
&lt;P&gt; &lt;/P&gt;</description>
      <link>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=54</link>
      <author>joe@rattz.com</author>
      <comments>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=54&amp;#Comments</comments>
      <guid isPermaLink="true">http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=54</guid>
      <pubDate>Fri, 12 Feb 2010 04:07:33 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://linqdev.com/PublicPortal/DesktopModules/Blog/Trackback.aspx?id=54</trackback:ping>
    </item>
    <item>
      <title>A Practical Lambda Expression Example For The UPS Tracking Web Service Call</title>
      <description>&lt;H1&gt;A Practical Lambda Expression Example For The UPS Tracking Web Service Call&lt;/H1&gt;
&lt;P&gt;In "Pro LINQ: Language Integrated Query in C# 2008" I provided an example of the evolution of named methods to anonymous methods and finally to lambda expressions.  I was illustrating the brevity that anonymous methods provide over named methods, and that lambda expressions provide over anonymous methods.  Just this week, while consuming the UPS Tracking web service, I have yet again found lambda expressions to be useful for this purpose.&lt;/P&gt;
&lt;P&gt;When compiling the UPS-provided test code, I received the following warning:&lt;/P&gt;
&lt;H1&gt;'System.Net.ServicePointManager.CertificatePolicy' is obsolete: 'CertificatePolicy is obsoleted for this type, please use ServerCertificateValidationCallback instead.&lt;/H1&gt;
&lt;P&gt;While it's just a warning and the code worked just fine, the code causing the warning has been obsolete for quite a while now so I thought I had better fix this now rather than potentially having to do it next time I upgrade to a new version of .NET.&lt;/P&gt;
&lt;P&gt;Here is the code causing the warning:&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;Here we are instantiating an object from a class named TrustAllCertificatePolicy.  That class implements the System.Net.ICertificatePolicy interface and here is the class code right from the UPS-provided test code:&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy&lt;BR&gt;{&lt;BR&gt;    public TrustAllCertificatePolicy()&lt;BR&gt;    { }&lt;/P&gt;
&lt;P&gt;    public bool CheckValidationResult(ServicePoint sp,&lt;BR&gt;      System.Security.Cryptography.X509Certificates.X509Certificate cert, WebRequest req, int problem)&lt;BR&gt;    {&lt;BR&gt;        return true;&lt;BR&gt;    }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;All that was really needed was just the CheckValidationResult callback function but it was implemented in .NET originally as an interface.  This requires creating a named class implementing the interface, instantiating an object of that named class type, and setting a reference to the object.  While this works, for a single callback, it is pretty verbose.  So, they made that obsolete and added a callback delegate type (thanks Jon Skeet for the terminology - C# in Depth - ISBN:  1-93398-836-3) that looks like this:&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;public delegate bool RemoteCertificateValidationCallback (&lt;BR&gt;    Object sender,&lt;BR&gt;    X509Certificate certificate,&lt;BR&gt;    X509Chain chain,&lt;BR&gt;    SslPolicyErrors sslPolicyErrors&lt;BR&gt;)&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;This would now allow you to call a named method.  So instead of this:&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;...&lt;BR&gt;System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();&lt;BR&gt;...&lt;BR&gt;public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy&lt;BR&gt;{&lt;BR&gt;    public TrustAllCertificatePolicy()&lt;BR&gt;    { }&lt;/P&gt;
&lt;P&gt;    public bool CheckValidationResult(ServicePoint sp,&lt;BR&gt;      System.Security.Cryptography.X509Certificates.X509Certificate cert, WebRequest req, int problem)&lt;BR&gt;    {&lt;BR&gt;        return true;&lt;BR&gt;    }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;You would have this:&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;...&lt;BR&gt;System.Net.ServicePointManager.ServerCertificateValidationCallback += CheckValidationResult;&lt;BR&gt;...&lt;BR&gt;public static bool CheckValidationResult(&lt;BR&gt;    object sender,&lt;BR&gt;    System.Security.Cryptography.X509Certificates.X509Certificate certificate,&lt;BR&gt;    System.Security.Cryptography.X509Certificates.X509Chain chain, &lt;BR&gt;    System.Net.Security.SslPolicyErrors sslPolicyErrors)&lt;BR&gt;{&lt;BR&gt;    return true;&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;Not bad.  We eliminated a single use class and no longer have to instantiate an object from it.  Anonymous methods make this even better so that you don't even have to write a named method.  Changing the code to use an anonymous method looks like this:&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;System.Net.ServicePointManager.ServerCertificateValidationCallback +=&lt;BR&gt;    delegate(&lt;BR&gt;        object sender, &lt;BR&gt;        System.Security.Cryptography.X509Certificates.X509Certificate certificate, &lt;BR&gt;        System.Security.Cryptography.X509Certificates.X509Chain chain, &lt;BR&gt;        System.Net.Security.SslPolicyErrors sslPolicyErrors)&lt;BR&gt;    {&lt;BR&gt;        return true;&lt;BR&gt;    };&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;Even better.  Not only do we no longer have a named class, we no longer have a named method.  This is great for single-use methods.  Now I'll take the last step and convert the code to use a lambda expression.  Ready?&lt;/P&gt;&lt;SPAN class=csharpcode&gt;
&lt;P&gt;System.Net.ServicePointManager.ServerCertificateValidationCallback += &lt;BR&gt;    (sender, certificate, chain, sslPolicyErrors) =&gt; true;&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;Wow, how about that!  No named class.  No named method.  No verbose delegate syntax.  Not even any parameter types.  I could have specified parameter types had I wanted to, but for brevity I did not.&lt;/P&gt;
&lt;P&gt;Changing the code from the initial, obsolete version, to the version using a lamda expression updated the code so that it is no longer obsolete and reduced the number of lines of code from twelve to two.  Not to mention how much easier it is to read and understand...once you understand lambda expressions.&lt;/P&gt;
&lt;P&gt;In all of these examples, the callback method simply returned true and you may need to update it for your needs.&lt;/P&gt;
&lt;P&gt;I hope this demonstrates how lamda expressions can simplify your code as well as resolve the obsolete warning you may be seeing if you are consuming the UPS tracking web service.&lt;BR&gt;&lt;/P&gt;</description>
      <link>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=52</link>
      <author>joe@rattz.com</author>
      <comments>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=52&amp;#Comments</comments>
      <guid isPermaLink="true">http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=52</guid>
      <pubDate>Wed, 03 Feb 2010 20:17:28 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://linqdev.com/PublicPortal/DesktopModules/Blog/Trackback.aspx?id=52</trackback:ping>
    </item>
    <item>
      <title>Using LINQ to Generate Test Data with the Range Operator</title>
      <description>&lt;H1&gt;Using LINQ to Generate Test Data with the Range Operator&lt;/H1&gt;
&lt;P&gt;When working on Pro LINQ, one of the operators that caught my attention is the Range operator.  The Range operator generates a sequence of integers.  At the time, this seemed like it could be very useful for generating test data.  I just used this again for a sample application I was working on and thought I should make a blog post about it.&lt;SPAN class=csharpcode&gt;&lt;/P&gt;
&lt;P&gt;int numItems = 200;&lt;/P&gt;
&lt;P&gt;var list = Enumerable.Range(1, numItems)&lt;BR&gt;                     .Select(i =&gt; new&lt;BR&gt;                       {&lt;BR&gt;                         Active = i &amp; 1,&lt;BR&gt;                         Id = i,&lt;BR&gt;                         Description = "Site " + i.ToString(),&lt;BR&gt;                         AccountNumber = "01015" + i.ToString("000"),&lt;BR&gt;                         City = "City Ville",&lt;BR&gt;                         State = "GA",&lt;BR&gt;                         Local = i &lt; 25,&lt;BR&gt;                         COJ = i % 3&lt;BR&gt;                       });&lt;/P&gt;
&lt;P&gt;SearchCombo.DataSource = list;&lt;BR&gt;SearchCombo.DataBind();&lt;/P&gt;
&lt;P&gt;&lt;/SPAN&gt;I have created a separate variable named numItems for the number of items I want to generate, but this obviously isn't necessary.  Next I call the Range operator to generate a sequence of integers containing however many items I want in the test.  I then call the Select operator on the sequence of integers and instantiate an anonymous object containing some sample data.  Please notice that I used the integer from the sequence in each anonymous object.  This of course isn't necessary either but makes for unique data.  Some of the anonymous object's members (Local and COJ) are just initialized with a somewhat random expression based on the integer just to give the test data a more random look.&lt;/P&gt;
&lt;P&gt;I then bind the generated sequence of test data to a combo box.  In this case, it is an Infragistics' WebCombo control.  Here is a screenshot.&lt;/P&gt;
&lt;P&gt;&lt;IMG border=0 alt=RangeDemo.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/RangeDemo.jpg" width=665 height=313&gt;&lt;/P&gt;
&lt;P&gt;Using the Range operator to generate test data can be very handy.&lt;/P&gt;</description>
      <link>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=50</link>
      <author>joe@rattz.com</author>
      <comments>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=50&amp;#Comments</comments>
      <guid isPermaLink="true">http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=50</guid>
      <pubDate>Wed, 21 Oct 2009 17:27:41 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://linqdev.com/PublicPortal/DesktopModules/Blog/Trackback.aspx?id=50</trackback:ping>
    </item>
    <item>
      <title>Pro LINQ: Language Integrated Query in VB 2008 Available and Shipping</title>
      <description>&lt;P&gt;My latest book, Pro LINQ: Language Integrated Query in VB 2008, was published on August 10, 2009, and is now available and shipping from Amazon.&lt;/P&gt;
&lt;P&gt;You may order it from &lt;A href="http://www.amazon.com/Pro-LINQ-Language-Integrated-Query/dp/1430216441?tag=netsplore-20" target=_blank&gt;Amazon&lt;/A&gt; or learn more about it at &lt;A href="http://www.apress.com/book/view/9781430216445" target=_blank&gt;Apress&lt;/A&gt;.&lt;/P&gt;</description>
      <link>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=48</link>
      <author>joe@rattz.com</author>
      <comments>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=48&amp;#Comments</comments>
      <guid isPermaLink="true">http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=48</guid>
      <pubDate>Wed, 12 Aug 2009 23:09:06 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://linqdev.com/PublicPortal/DesktopModules/Blog/Trackback.aspx?id=48</trackback:ping>
    </item>
    <item>
      <title>Final Edits For Pro LINQ: Language Integrated Query in VB 2008 Have Been Submitted!</title>
      <description>I just turned in the final edits for my Pro LINQ: Language Integrated Query in VB 2008 book.  That means it should actually be available in early August.

Now I just have to update this site for it.</description>
      <link>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=47</link>
      <author>joe@rattz.com</author>
      <comments>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=47&amp;#Comments</comments>
      <guid isPermaLink="true">http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=47</guid>
      <pubDate>Sun, 12 Jul 2009 06:17:23 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://linqdev.com/PublicPortal/DesktopModules/Blog/Trackback.aspx?id=47</trackback:ping>
    </item>
    <item>
      <title>Using LINQ to Obtain a Control Reference in an ASP.NET Repeater Item's ControlCollection</title>
      <description>&lt;P&gt;I haven't been blogging about LINQ much, but I am making it a new year's resolution to blog more frequently about LINQ.  Now, don't expect daily or even weekly blog posts because I am just not as prolific as some bloggers.  I don't know how some bloggers do it.  But, I do plan on blogging more frequently.&lt;/P&gt;
&lt;P&gt;One of my favorite, but under-utilized, ASP.NET controls is the Repeater.  I think it exemplifies what it is that we like so much about the web; that is, the graphic representation of data.  Sure, I use web grids more frequently, but when you have multiple instances of data that just doesn't fit in a single line well, the Repeater is the answer.  Consider listings of homes for sale, or cars.  You typically see an image of the house or car, and several fields of information.  There are usually so many fields, that the data will just not fit in a single line in a grid.  Plus, the image would make the line very tall.  Using a Repeater, each repeating instance of data can have a format and occupy a rectangular screen space that is much taller than a row in a web grid, and you are not locked into an NxN grid.  Here are a couple of examples of repeaters I have used:&lt;/P&gt;
&lt;P&gt;&lt;IMG height=448 alt=NewspaperWithRepeaters.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/NewspaperWithRepeaters.jpg" width=850 border=0&gt;&lt;/P&gt;
&lt;P&gt;In the image above, I have a page that is a mock-up of a newspaper, complete with columns.  The idea with this page is here is all the news that is relevant to you, and it includes the user's Orders, Credits, and Invoices.  Each item in one of the columns is a link to the item on another page where they can see all the data associated with that item.  This page is neat because it lets the user see all their items from the week on a single page.  Like a newspaper, you can see the price of the newspaper in the top right corner, and you can see a wink to the MasterCard "priceless" commericals there.  That page has three Repeaters on it; one each for the Orders, Credits, and Invoices.  Notice that each item in the Repeater has a specific format, and that the format for each Repeater (column) is slightly different.  This is the beauty of the Repeater.&lt;/P&gt;
&lt;P&gt;In the image below is a Repeater I use that contains a list of stores the user can import into their account.  Again we are looking at repeating items with each item having a format.  Please notice that there is a checkbox in each repeating item.  Also notice that there is a Select All checkbox outside the Repeater.  The purpose of the Select All checkbox is to select the checkbox in each repeating item.&lt;/P&gt;
&lt;P&gt;&lt;IMG height=350 alt=MissingStoresWithRepeater.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/MissingStoresWithRepeater.jpg" width=427 border=0&gt;&lt;/P&gt;
&lt;P&gt;On that page, I use a third-party set of web UI controls and during a recent upgrade of that control suite, something broke.  When this happens, I need to create a sample application to demonstrate the problem, and the simpler it is, the better.  As is always the case, my real application is too big, too complex, and dependent on too many environmental conditions to be able to provide the real page.  Below is an image of the sample application I created to reproduce the problem that I could provide to the control's vendor.&lt;/P&gt;
&lt;P&gt;&lt;IMG height=152 alt=RepeaterCheckboxes.jpg src="http://linqdev.com/PublicPortal/Portals/5/images/RepeaterCheckboxes.jpg" width=284 border=0&gt;&lt;/P&gt;
&lt;P&gt;In the image above, you can see a Select All checkbox followed by a list of checkboxes below it.  Those checkboxes are items in a Repeater.  When the user clicks the Select All checkbox, an AJAX postback is made to some code that enumerates through the Repeater's items, finds the checkbox in each item's template (ControlCollection), and checks (or unchecks depending on the state of the Select All checkbox) the Repeater item's checkbox.&lt;/P&gt;
&lt;P&gt;Now here's probably the worst part of using a Repeater, dealing with the item's template.  Since the Repeater uses a template, to obtain a reference to any control in the template, you must find the control in the Repeater item's ControlCollection.  Prior to LINQ, that meant enumerating through the item's ControlCollection checking each control to see if it is the one you want.  With LINQ, that is no longer necessary.  Here is my code to obtain a reference to the CheckBox control in each item:&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;SPAN class=csharpcode&gt;    protected void CheckBox1_CheckedChanged(object sender, EventArgs e)&lt;BR&gt;    {&lt;BR&gt;        foreach (RepeaterItem item in Repeater1.Items)&lt;BR&gt;        {&lt;BR&gt;            CheckBox cb = (CheckBox)item.Controls&lt;BR&gt;                                        .Cast&lt;Control&gt;()&lt;BR&gt;                                        .Where(c =&gt; c.ID == "CheckBox2")&lt;BR&gt;                                        .SingleOrDefault();&lt;BR&gt;            if (cb != null)&lt;BR&gt;            {&lt;BR&gt;                cb.Checked = CheckBox1.Checked;&lt;BR&gt;            }&lt;BR&gt;        }&lt;BR&gt;    }&lt;/SPAN&gt;&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Notice that I enumerate through the Repeater's items.  Next, I call the Cast operator on each item's ControlCollection (named Controls) because ControlCollection is a legacy collection that doesn't implement IEnumerable&lt;T&gt;.  I then call the Where operator on the sequence of Control objects returned by the Cast operator to find just the controls whose ID is equal to the ID I specified for the CheckBox in the template, which is "CheckBox2".  Last, I call the SingleOrDefault operator to get a reference to that single control.  I then check to make sure I got a reference, as opposed to null, and if I did get a reference, I set that control's Checked property equal to the Select All checkbox's Checked property.  Voila, just that easy with a LINQ query, I now have a reference to a control in an ASP.NET Repeater control item's ControlCollection.&lt;/P&gt;
&lt;P&gt;This is a fine demonstration of how to use LINQ to query legacy collections that do not implement the IEnumerable&lt;T&gt; interface, as well has how to easily find a control by ID in a ControlCollection.  Who said LINQ isn't fun?&lt;/P&gt;
&lt;P&gt;&lt;BR&gt; &lt;/P&gt;</description>
      <link>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=44</link>
      <author>joe@rattz.com</author>
      <comments>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=44&amp;#Comments</comments>
      <guid isPermaLink="true">http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=44</guid>
      <pubDate>Fri, 23 Jan 2009 19:22:41 GMT</pubDate>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://linqdev.com/PublicPortal/DesktopModules/Blog/Trackback.aspx?id=44</trackback:ping>
    </item>
    <item>
      <title>LINQ to SQL Has a Future Despite the Rumors</title>
      <description>&lt;P&gt;For the last several months, I have repeatedly heard a rumor that there was no future for LINQ to SQL.  One reader even informed me that they heard LINQ to SQL was going to be snuffed and that because of this, their company changed architectural direction away from LINQ to SQL.&lt;/P&gt;
&lt;P&gt;Concerned that the rumors may be either true and some developers are on a dead end path, or false and LINQ to SQL adoption may be suffering unnecessarily as a result of the rumors, I emailed Scott Guthrie at Microsoft to get his position on the future of LINQ to SQL.&lt;/P&gt;
&lt;P&gt;Scott told me "Regarding LINQ to SQL, we definitely don't have plans to drop this.  We plan to continue to fully support this going forward.".&lt;/P&gt;
&lt;P&gt;Scott continued with "I actually blog most of my samples using LINQ to SQL these days (I just did one last week on ASP.NET MVC form scenarios and used LINQ to SQL for the data access).  Expect to see me continue to blog more about it in the future.".&lt;/P&gt;
&lt;P&gt;Here is a link to the blog post Scott refers to:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://weblogs.asp.net/scottgu/archive/2008/09/02/asp-net-mvc-preview-5-and-form-posting-scenarios.aspx" target=_blank&gt;http://weblogs.asp.net/scottgu/archive/2008/09/02/asp-net-mvc-preview-5-and-form-posting-scenarios.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;If you read the blog post, you will see Scott using LINQ to SQL.&lt;/P&gt;
&lt;P&gt;Further evidence of a commitment to LINQ to SQL is the work of Damien Guard, a Microsoft employee that works on LINQ to SQL.  Here is a link to his personal blog:  &lt;A href="http://damieng.com/" target=_blank&gt;http://damieng.com/&lt;/A&gt;&lt;BR&gt;&lt;/P&gt;</description>
      <link>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=36</link>
      <author>joe@rattz.com</author>
      <comments>http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=36&amp;#Comments</comments>
      <guid isPermaLink="true">http://linqdev.com/PublicPortal/Default.aspx?tabid=281&amp;EntryID=36</guid>
      <pubDate>Mon, 22 Sep 2008 15:15:51 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://linqdev.com/PublicPortal/DesktopModules/Blog/Trackback.aspx?id=36</trackback:ping>
    </item>
  </channel>
</rss>