Rants

<<  <  1  2  3  4  5  6  7  8  9  10  11  +  >  >>  (Total Pages: 91/Total Results: 910)

Book Review: The Productive Programmer - Neal Ford

Silverlight Logo

I've been reading Neal's blog for a while so when this book was launched I wanted to get a copy. I expected a more esoteric book from Neal, but this book was exceptionally applicable. His advice on the nature of being productive including links to specific tools impressed me a lot. I also admired his even handedness in his treatment of operating systems. Its hard to find someone that will talk about Microsoft and Apple technologies without religiosity. When it was good in Windows, he mentioned it. When it was good in OSX, he mentions it.

Maybe its because I am an old guy, but I thought his commentary about how much tools are making us soft (my term, not his) was nice to hear. Having used a simple text editor to do most of my coding the first decade of development, ideas like Intellisense and background complication make me a little crazy.  

On the writing side, his prose is well thought out and exceptionally readable. You can get through the book pretty quickly but I found my self post-it noting a bunch of pages to revisit. The book is chocked full of well thought out specific advice for developers to help them be more productive.

I wholeheartedly recommend this book to every developer, no matter your technology (Windows, OSX, .NET, Java, RoR, etc.)

Speaking at the Atlanta .NET Users Group

Silverlight Logo

Next Monday night (July 28th, 2008), i'll be giving the short Q&A session at the Atlanta .NET Users Group.  The topic?  NHibernate's LINQ and ADO.NET Data Services support.  If you're interested in using NHibernate but don't want to give up your LINQ skills, stop by for a listen!

Silverlight Tour: Boston - August 11th-13th

Silverlight Logo

In case you read my blog and didn't know that we were coming to Boston, what are you waiting for? We will be in Boston for the Silverlight Tour on August 11-13th, 2008.  If you're interested in signing up, we are not full yet!

NHibernate.LINQ with ADO.NET Data Services

Silverlight Logo

Now that my ADO.NET Data Services support has been merged into the trunk of NHibernate.LINQ, I do have some caveats about using NHibernate.LINQ with ADO.NET Data ServicesADO.NET Data Services is a beta 1 product so there are some bugs and issues that you will either need to avoid or work around.

The biggest issue is around entity identity. ADO.NET Data Services must know how identity is established for objects in order to support the Data Service. It does this in a two step process:

  • First it looks for attributes that describe the 'primary key'.
  • Failing that, it looks for properties on the entity called ID, or ending with "ID".

The second approach is where I expect most of NHibernate projects to fall into since you really don't want to pollute your objects with technology specific information (the attributes). This approach works well except that there is a bug in the Beta 1 version of ADO.NET Data Services.  If the properties are specified in a base class and the keys are specified ending in "ID" (instead of just being called "ID"), then the search for the identifiers fails and Data Services fails to want to serve these objects.  For example:

public class AbstractCategory
{
  public virtual int CategoryID { get; set; }

  public virtual string CategoryName { get; set; }

  public virtual string Description { get; set; }

  public virtual byte[] Picture { get; set; }

  public virtual IList Products { get; set; }
}

public class Category : AbstractCategory
{
}
}

If this is your scenario, I might suggest waiting for later build of ADO.NET Data Services to be released as this is definitely a bug not expected behavior and I have gotten word from Microsoft that it is fixed in the RTM (which isn't available yet).

The next issue is that for collections, ADO.NET Data Services must understand the types that belong in a collection. In this case our above example will not work either in that having the Products in a Category as a simple IList can't tell ADO.NET Data Services what types of objects to deal with.  If we change this to an IList<Products>, it works fine.  If we have to change our entities to work with ADO.NET Data Services, this is what our new Category might look like instead:

public class Category
{
  public virtual int CategoryID { get; set; }

  public virtual string CategoryName { get; set; }

  public virtual string Description { get; set; }

  public virtual byte[] Picture { get; set; }

  public virtual IList<Product> Products { get; set; }
}

With these changes, ADO.NET Data Services work fine.

If you are new to ADO.NET Data Services, this blog entry may help with some debugging issues in using it:

http://wildermuth.com/2008/06/07/Debugging_ADO_NET_Data_Services_with_Fiddler2

Lastly, I want to follow up on a note that Ayende mentioned on his announcement of my examples.  In his blog post, he said:

From a technological perspective, I think this is awesome. However, there are architectural issues with exposing your model in such a fashion. Specifically, with regards to availability and scalability on the operations side, and schema versioning and adaptability on the development side.

I think he's right in that there is a schema version issue here that needs to be addressed but that the availability and scalability problems are ones that would be in the underlying data model itself. Since ADO.NET Data Services are just a convenience around WCF's REST Service Model, we can scale out or up depending on our needs (as well as caching).

What I think is important is to understand the reason behind ADO.NET Data Services.  It is not a model to replace typical Web Service or Message Bus architectures.  Its not all that fast or efficient.  Its purpose is to allow the creation of a simple model to allow communication across the firewall.  What I mean is that it is meant for the AJAX and RIA developers.  Its a way of communicating data to clients that run on the Internet. 

Its important to understand that data you expose with ADO.NET Data Services is not magically more secure...in fact, since its meant for client-side consumption of data, you should not allow data to be exposed by ADO.NET Data Services that is sensitive. Remember, that consuming data in the client is not secure in itself.  If you wouldn't feel safe consuming data in client-side JavaScript, don't expose it via ADO.NET Data Services.

Silverlight 2 + NHibernate.LINQ == Sweet

Silverlight Logo

UPDATE: Looks like I uncovered a ADO.NET Data Services bug in FF3.  The examples will only work with IE and Safari at the moment.

After a couple of weeks on and off the project, I finally finished the first stab at adding ADO.NET Data Services support to NHibernate.LINQ. To accomplish this I've added three features:

  • Support for IUpdateable to support full NHibernate CRUD.
  • Support for a new Expand extension method to do eager loading via the LINQ interface.  (The Expand method is similar to Entity Framework's Include method.)
  • Finally, using the Expand extension method, I implemented the IExpandProvider interface to allow for expansions via the REST API.

These changes have been posted to the NHContrib project (where the NHibernate.LINQ lives) to allow the committers to validate and add it to new versions of the project. I am sure that it will need some refactoring and tweaking but the basics are done.

In addition, I'll be finishing up my discussion of implementing the IUpdateable interface pretty soon to help those of you adding this support to your projects. I'll also be blogging about how I added the IExpandProvider to help those of you trying to add that to your projects (or even to LINQ to SQL).

To prove out this new support, I've launched a new version of my Simple ADO.NET Data Services project with a NHibernate flavor.  Go visit http://www.silverlightdata.com to see it working.  In addition, I updated that sample to include paging support to make it a little more performant.

Let me know what you think.

Animating Brushes with ObjectAnimationUsingKeyFrames

Silverlight Logo

In my recent class I had a student ask me about animating a brush. I quickly dove into how to animation a *color* in a brush and he indicated that isn't what he wanted.  He had a resource-based brush that he wanted to switch out in the Visual State Manager.  In Blend when he was setting the Brush during the animation recording of the MouseOver event but that wasn't creating a storyboard but changing the natural brush of the control. To solve this we had to dive into the XAML as Blend doesn't seem to know about the ObjectAnimationUsingKeyFrames animation type.

First a small discussion about animations.  Normally animations will take a value and transition between the values.  For example a DoubleAnimation that is set up to change the Opacity of a visual element from zero to one, will interpolate the values to create a smooth transition from invisible to visible. Keyframed animations support several types of interpolation including linear (the default), spline and discrete.  Linear keyframes simply create a smooth transition between values.  Spline keyframes allow you to shape the interpolation between the values to ease-in or ease-out the transition.  Lastly, the Discrete keyframes set a value at the time of the keyframe without any interpolation.

The ObjectAnimationUsingKeyFrames animation allows you to use object instead of primitive values for your animation keyframes. The only type of keyframe allowed in the ObjectAnimationUsingKeyFrames animation are Discrete keyframes.  The reason is that there is no good way to interpolate between object values. So back to our original problem, animation a Brush.  In the MouseOver state, the student wanted to change the Fill of a rectangle from one resource-based Brush to another.  For example, here are the brushes defined in the Resources section:

<UserControl.Resources>
  <LinearGradientBrush x:Key="backBrush"
                       EndPoint="0.5,1"
                       StartPoint="0.5,0">
    <GradientStop Color="#FFFF0000" />
    <GradientStop Color="#FFE50000"
                  Offset="1" />
  </LinearGradientBrush>
  <LinearGradientBrush x:Key="mouseOverBackBrush"
                       EndPoint="0.5,1"
                       StartPoint="0.5,0">
    <GradientStop Color="#FF006DFF" />
    <GradientStop Color="#FF0064E9"
                  Offset="1" />
  </LinearGradientBrush>
  
  ...

The student had set the backBrush to the Rectangle's fill during the design phase and wanted to set the mouseOverBackBrush during the Visual State Manager's MouseOver state. Since Blend wouldn't let us do it, we had to write the ObjectAnimationUsingKeyFrames XAML ourselves.

To do this, we created a Storyboard and an ObjectAnimationUsingKeyFrames element inside the MouseOver state (of the Visual State Manager for our Button's ControlTemplate).  In the new element we specified the Storyboard.TargetName and Storyboard.TargetProperty to "theBack" and "Fill". Inside the animation, we created a DiscreteObjectKeyFrame for our one value.  We just wanted to change it to the since new brush so we only needed one.  We set the Keytime to "0:0:0" to specify that this should happen immediately.  Lastly, we specified the StaticResource for the mouseOverBackBrush as the Value. Here's the entire MouseOver state XAML:

...
<VisualState x:Name="MouseOver">
  <Storyboard>
    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="theBack"
                                   Storyboard.TargetProperty="Fill">
      <DiscreteObjectKeyFrame KeyTime="0:0:0"
                              Value="{StaticResource mouseOverBackBrush}" />
    </ObjectAnimationUsingKeyFrames>
  </Storyboard>
</VisualState>
...

We didn't need to specify another animation in the Normal state the Visual State Manager automatically handles the resetting of our value back to the original state. It just works.  Here's two pictures of the button before and after the mouse over:

You can download the example here.

Silverlight 2 Hotfix just hit Windows Update

Silverlight Logo

Short and sweet...if you are having Silvelright 2 Beta 2 issues with Firefox and media streaming, make sure you check Windows Update for a new fix.  I think the OSX guys can just visit a Silverlight page to get it (using the auto-update stuff).

Experimenting with Adobe AiR

Silverlight Logo

I was under a false impression. I've been using Twhirl for my Twitter client needs as it was the most feature complete client i could find. Twhirl requires the Adobe AiR runtime to work. I thought that AiR was a wrapper around Flex to allow desktop installation of Flex. What I didn't understand was that AiR is a runtime to allow Flex, Flash and HTML/AJAX apps to be hosted as a windowed desktop application. Interesting...so AiR isn't necessarily about Flex, but for all three platforms.

HTML/AJAX you say? Silverlight 2 is hosted on HTML. Could I do the scandalous thing and make my Silverlight 2 application run as an AiR application? It was to the SDK I ran.

With the AiR SDK in hand, I followed their walk-through to create my first small AiR app.  Its an interesting model that creates AiR apps out of a bunch of resources. So, in theory Silverlight could work. Silverlight.js, .xap files, and other resources are just files.  It should work...but it doesn't. The problem is that when hosted in AiR, the Silverlight ActiveX object doesn't want to be created.  I am not sure if this is an issue with AiR or Silverlight. I've seen examples of other web-friendly ActiveX (or object tags) working (e.g. PDF Viewer) in AiR, so my guess is Silverlight 2.

I didn't expect to get much in the way of examples from other people, but I did expect to find some good community support for AiR...but even the Adobe public forum for AiR had zero messages (I think its broken, not empty).

So I plead to my readers: if any of you know of any good AiR resources (developer-to-developer preferred), please add a comment here.  It'd be cool to actually get this to work.

Geek Dinner in Chicago - July 14th, 2008

Silverlight Logo

Since I'll be in Chicago for a stop of the Silverlight Tour, we will be holding an informal geek dinner on Monday night.  We are holding it at:

Real Time Sports Bar

1120-22 West Devon Ave.
Elk Grove Village, IL 60007
Phone: (847) 534-5000

We will be meeting in the Bar area at 6:30pm and grab a seat for dinner around 7pm.  If you can make it please, RSVP by going to the dinner:

http://www.geekdinners.com/DinnerInstance.aspx?id=11

Wildermuth.com By Example - Part 1

Silverlight Logo

In response to some requests that I have received, I decided to write a several part blog on some of the techniques I used in developing Wildermuth.com. In this first example, I am going to discuss the use of LINQ and data in my site. 

In moving from www.adoguy.com to www.wildermuth.com, one of my goals was to use LINQ as much as possible to see the travails of using it on a real project. I have done a lot of small samples with LINQ but did it hold up for real work?  Suffice to say I am pretty impressed (though whether a blog is 'real work' is up for discussion, but its a better exercise of the technology than my samples had been).

When I say LINQ, I want to be specific.  LINQ to me really is "Language Integrated Query".  The data store behind is a secondary discussion and whether the Entity Framework, LLBLGen Pro, or nHibernate, I really wanted to make sure that the way I queried data in the C# code was LINQ. I was hoping to avoid dropping down into SQL as much as possible.

I knew I wanted to be able to use my model from most pages so I added the data context to the Master page so it would handle most of the build-up, tear-down for me:

public WilderEntities Ctx
{
  get
  {
    if (_ctx == null)
    {
      _ctx = new WilderEntities();
    }

    return _ctx;
  }
}

protected override void OnUnload(EventArgs e)
{
  if (_ctx != null)
  {
    Ctx.Dispose();
  }
}

This allowed me to create the Ctx on the master page but use it on any page/control that I neeeded.  The disposal of the context would happen during unloading of the the page.  The only thing that this required is that most pages needed a typed reference to the master page which you can do with a MasterType page directive:

<%@ Page Language="C#" MasterPageFile="~/StwMaster.Master" 
    AutoEventWireup="true" CodeBehind="default.aspx.cs"
    Inherits="stw._default" Title="Shawn Wildermuth's Blog" %>

<%@ MasterType VirtualPath="~/StwMaster.Master" %>

Much of the LINQ code is fairly pedestrian:

var qry = from b in MasterPage.Ctx.BlogEntry.Include("BlogEntryComments")
          where b.Published == true
          orderby b.DatePosted descending
          select b;

List<BlogEntry> rants = qry.Take(10).ToList();

 

You can see that I am doing a simple LINQ query to get all the published BlogEntry objects and order them by the date they were posted.  Of note, when I execute the query I am adding the Take() method to limit the results.  This is akin to TOP in SQL and we'll be revisiting it in a minute.

Because I need to have access to comments about the blog entries, I use the Include clause in the LINQ query to retrieve not only the BlogEntry objects, but also the related BlogEntryComment objects. This syntax is specific to the EntityFramework. If you are using a different LINQ provider, you may find that lazy loading is automatic (e.g. nHibernate) or not available.  I know this is a chief complaint about the Entity Framework, but I like it as it makes the developer have to think about loading sub-types and the side effects...but that's a whole other discussion.

Once we have a result its a simple as assigning our collection and forcing data binding to happen:

theRants.Blogs = rants;
titles.Blogs = rants;
DataBind();

 

Of particular interest here is that I am using the same list to bind to two collections (the list of blogs and the "On This Page" titles).   Because we are getting simple CLR object collection back, there isn't any magic here in how we're doing the binding.  This is in stark contrast to older data access (e.g. DataRows, DataReaders).

One thing I really like here is that I can do the paging directly during the execution of the LINQ query as seen in the LINQ query for the paged Rants page:

var qry = from b in Master.Ctx.BlogEntry.Include("BlogEntryComments")
          where b.Published == true 
          orderby b.DatePosted descending
          select b;

List<BlogEntry> rants = qry.Skip(PAGESIZE * (currentPage - 1)).Take(PAGESIZE).ToList();

 

Note that this LINQ query is identical to the earlier home page query but I am doing the paging by calculating both the Skip() and Take() value.  Like I mentioned earlier, Take() is like TOP in that it specifies the number of returned elements.  Whereas Skip() specifies how many results to ignore before starting the Take() amount. This allows us to manage paging directly using the LINQ code.

There was one place where I just couldn't get LINQ to bend to my wishes.  I am still not convinced that there is *not* a way to do this, but I dove down into Entity SQL to make the request instead. The case was where I am translating the URI pieces of the Rant URI (e.g. http://wildermuth.com/2008/07/07/Wildermuth_com_By_Example_-_Part_1) where I am being handed the year, month, day and title by the routing framework (I'll talk about that in a future post).  I needed a way of finding the right Rant based on that information (since I don't want to share the Rant ID with anyone). To do this, I used an ObjectQuery (Entity Framework's query syntax using Entity SQL):

string whereClause = @"SqlServer.DATEPART('yyyy', it.DatePosted) = @year AND 
                       SqlServer.DATEPART('mm', it.DatePosted) = @month AND 
                       SqlServer.DATEPART('dd', it.DatePosted) = @day AND 
                       it.Title LIKE @pattern";
ObjectQuery<BlogEntry> qry = Master.Ctx.BlogEntry
                                  .Include("BlogEntryComments")
                                  .Where(whereClause);

qry.Parameters.Add(new ObjectParameter("year", rantDate.Year));
qry.Parameters.Add(new ObjectParameter("month", rantDate.Month));
qry.Parameters.Add(new ObjectParameter("day", rantDate.Day));
qry.Parameters.Add(new ObjectParameter("pattern", pattern));

_blogEntry = qry.FirstOrDefault();

 

Note I am using the DATEPART syntax to compare the parts of the date.  The real issue with the query was the parameter as I take the title and replace all underscores with % to do a LIKE query.  This worked fine and once the query executes, I am dealing with a simple CLR object so it doesn't matter in the bit picture.

Other than that, the LINQ syntax is pretty straightforward in my example.  I ported old old nasty code from my original sites (in fact some routines were originally ported from ASP to ASP.NET back in pre v1.0).  Because of that I don't have a good separation of responsibilities, but that's for the next conversion...when MVC comes of age.

My last note I wanted to say is that I attempt to create pretty simple HTML. I don't use many actual controls except the repeater and create mostly CSS-based XHTML to be simple. With that in mind I enchew ASP.NET's DataSource stuff.  Whether its LINQ, Object or Sql DataSources they all are trying to do a lot of magic IMHO and I end up writing code instead of depending on them.

Opinions and observations are welcome!