July 22, 2008 by
ryan
I really wish Visual Studio / SQL Server Management Studio had column editing support similar to text editors like Crimson Edit. I find myself using the column edit alot when running quick, one off SQL Queries or making the same change to multiple lines in VS. I know a lot of this functionality can be replicated with macros but it seems to be a lot faster to just hit column editing mode and type away.
View my demo of Crimson Editor's Column Edit Mode. (Wink seems to slow down and speed up certain parts of the recording -- especially when a dialog window is open.)
July 8, 2008 by
ryan
Justin Etheredge recently tagged me to write up how I got started in software development (you are probably familiar with the meme started by Michael Eaton). Without any further explanation, here goes:
How old were you when you first started programming?
I first started programming when I was 10 or 11 (I don't remember exactly).
How did you get started in programming?
My interest in programming initially began as a general interest in computer games. My dad showed me how to get around in DOS and pulled up some games in QBasic. It wasn't long after that I started messing with the code to see what would happen if I changed things. From there, I tried writing some stuff on my own spending a lot of time in the syntax help.
What was your first language?
BASIC
What was the first real program you wrote?
Depending on the definition, the first real program I wrote was a game that worked in an AOL chat room. When I was 13, one of my friends showed me this thing called a scrambler. The scrambler would let you enter a word, send the scrambled word to the chat and keep score of who got the word right first, etc. I don't know why but I thought it would be an interesting thing to try and replicate. About a month later, I had finished writing one using the VB and the Windows API. It was not very useful but I learned a lot that way I guess.
What languages have you used since you started programming?
C#, VB.NET, Java, JavaScript, Ruby, Perl, PHP, BASIC, C, C++, F# (and others)
What was your first professional programming gig?
When I was in Highschool/College I did some freelance websites/applications mainly for construction and contracting companies. After college my first full-time programming job was working at Franklin University on the development team (websites / web applications).
If you knew then what you know now, would you have started programming?
Absolutely.
If there is one thing you learned along the way that you would tell new developers, what would it be?
Be continuously learning.
What's the most fun you've ever had programming?
I honestly couldn't tell you -- there are a lot of projects that have been really fun. I especially like when there's some new kind of challenge I haven't encountered before.
Who are you calling out?
Matt Braun
Scott Sanzenbacher
Rob Conery
Jurgen Appelo
Danny Douglass
Oren Eini
April 30, 2008 by
ryan
As mentioned in my last post, I've been starting to use NHibernate in some of my more recent projects. I checked it out years ago and I completely hated it (maybe becuase I was a newer developer -- not totally sure). More recently, however, I've realized some of the benefits of Domain Driven Design and thought its about time to give Hibernate another shot. I'm admittedly pretty new to Hibernate so any feedback would be appreciated!
Classes
public class ProductGroup
{
public virtual string ProductGroupID { get; set; }
public virtual string Title{ get; set;}
public virtual IList<SimpleProduct> Products { get; set; }
}
public class SimpleProduct
{
private IList<SimpleProduct> _relatedProducts;
public virtual string ID { get; set; }
public virtual string Title { get; set; }
public virtual string ImagePath { get; set; }
public virtual string Description { get; set; }
public virtual IList<SimpleProduct> RelatedProducts
{
get{ return _relatedProducts; }
private set { _relatedProducts = value; }
}
public virtual void AddRelatedProduct(SimpleProduct product)
{
if (_relatedProducts == null)
_relatedProducts = new List<SimpleProduct>();
_relatedProducts.Add(product);
}
}
We're going to start out with some very contrived classes (normally would start with tests but this is just for the hibernate concepts)... These classes should be pretty straight forward; they consist only of some basic properties and list methods.
Data Tables
Next, we need to create our tables to hold the data coming from the Classes -- I've created a product table / product group table and a lookup table for both (there are many-to-many references in both SimpleProduct and ProductGroup).
CREATE TABLE [dbo].[SimpleProducts](
[ProductID] [char](32) NOT NULL,
[Title] [nvarchar](50) NOT NULL,
[ImagePath] [nvarchar](300) NULL,
[Description] [nvarchar](500) NULL
)
CREATE TABLE [dbo].[RelatedProductsLookup](
[ProductID] [char](32) NOT NULL,
[RelatedProductID] [char](32) NOT NULL
)
CREATE TABLE [dbo].[ProductsProductGroupsLookup](
[ProductGroupID] [char](32) NULL,
[ProductID] [char](32) NULL
)
CREATE TABLE [dbo].[ProductGroups](
[ProductGroupID] [char](32) NOT NULL,
[Title] [nvarchar](50) NULL
)
You will want to set the Primary Key of the SimpleProduct and Product Groups table to be the ID.
Hibernate Mappings
Next we're on to the Hibernate mapping files. These files link the columns in the database to the fields/properties in the domain classes. Please check the project documentation for more detailed information on the Hibernate Schemas.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="ProductModel" assembly="ProductModel" default-lazy="false">
<class name="ProductGroup" table="ProductGroups">
<id name="ProductGroupID">
<column name="ProductGroupID" sql-type="char(32)" not-null="true" />
<generator class="uuid.hex" />
</id>
<property name="Title">
<column name="Title" length="50" not-null="true" />
</property>
<bag name="Products" table="ProductsProductGroupsLookup" lazy="false">
<key column="ProductGroupID" />
<many-to-many class="SimpleProduct" column="ProductID" />
</bag>
</class>
</hibernate-mapping>
Inside the hibernate mapping tag, we have an element called class where we're defining the relationship between the class and the table in the database. From there we're defining the properties -- Most of this should be pretty straight forward but there are a couple things I would like to focus on.
<id name="ProductGroupID">
<column name="ProductGroupID" sql-type="char(32)" not-null="true" />
<generator class="uuid.hex" />
</id>
This node is defining the unique ID for the class -- the ID is being created for each item and looks a little something like this: 46abbefc08d14b49a5d15c8a4dd69ff2
<bag name="Products" table="ProductsProductGroupsLookup" lazy="false">
<key column="ProductGroupID" />
<many-to-many class="SimpleProduct" column="ProductID" />
</bag>
</class>
Here we're defining a many-to-many relationship with Products -- this is bumping up against the lookup table we defined earlier to get all SimpleProducts associated with this class. currently the bag is defining a many-to-many relationship. We're going to assume that a product can exist under any number of product groups -- for instance if we have a video game system it could be under both the Home Entertainment and Electronics product group. See the project documentation for other types of relationships (one-to-many, etc).
SimpleProduct Mapping:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="ProductModel" assembly="ProductModel" default-lazy="false">
<class name="SimpleProduct" table="SimpleProducts">
<id name="ID">
<column name="ProductID" sql-type="char(32)" not-null="true" />
<generator class="uuid.hex" />
</id>
<property name="Title">
<column name="Title" length="50" not-null="true" />
</property>
<property name="ImagePath">
<column name="ImagePath" length="300" not-null="false" />
</property>
<property name="Description">
<column name="Description" length="500" not-null="false" />
</property>
<bag name="RelatedProducts" table="RelatedProductsLookup" lazy="false">
<key column="ProductID" />
<many-to-many class="SimpleProduct" column="RelatedProductID" />
</bag>
</class>
</hibernate-mapping>
Accessing The Data
Now that we've defined all of our mappings its time to create some methods to access our data.
public class ProductGroupRepository
{
private ISession _session;
public ProductGroupRepository(ISession session)
{
_session = session;
}
public ProductGroup GetByTitle(string Title)
{
return _session.CreateCriteria(typeof(ProductGroup))
.Add(Expression.Eq("Title", Title))
.UniqueResult<ProductGroup>();
}
public IList<ProductGroup> List()
{
return _session.CreateCriteria(typeof(ProductGroup))
.List<ProductGroup>();
}
}
The ISession is the Hibernate object to use when accessing the data -- from what it looks like, these should pretty much line up with a unit of work (More on that here).
In the other methods of the class, we first need to define what type of object we're looking for. In case it's not obvious, we're specifying that in the CreateCriteria section. In the List() method, we're returning a list (of ProductGroups) -- there are no filters or other criteria defined for this operation. In the GetByTitle() method, however, we're stating that the Title for the product must match the Parameter 'Title'.
Demo Application
I've created a quick demo application using MVC and NHibernate. As I said, I'm still very new to hibernate so there's a lot I'm trying to learn (for instance where the ISession should initially be created and closed in an MVC application). Please let me know of any way that this could be better -- generally I'm writing this to help solidfy my thoughts on the technology, help others (hopefully) and also improve from others feedback.
If you have tortoise or some other svn client, you can grab the code from http://svn2.assembla.com/svn/NHibernateTest/ -- You will need to change the database connection to whatever your db is. Again I would like to reiterate, it's demo code -- not even close to anything that I would ever use in production but worked out okay for testing.
Disclaimer: Use this code at your own risk.