Index: Rhino.Etl.Core/Row.cs
===================================================================
--- Rhino.Etl.Core/Row.cs	(revision 1867)
+++ Rhino.Etl.Core/Row.cs	(working copy)
@@ -1,3 +1,6 @@
+using Rhino.Commons;
+using System.Linq;
+
 namespace Rhino.Etl.Core
 {
     using System;
@@ -13,7 +16,7 @@
     [DebuggerDisplay("Count = {items.Count}")]
     [DebuggerTypeProxy(typeof(QuackingDictionaryDebugView))]
     [Serializable]
-    public class Row : QuackingDictionary
+    public class Row : QuackingDictionary, IEquatable<Row>
     {
         static readonly Dictionary<Type, List<PropertyInfo>> propertiesCache = new Dictionary<Type, List<PropertyInfo>>();
         static readonly Dictionary<Type, List<FieldInfo>> fieldsCache = new Dictionary<Type, List<FieldInfo>>();
@@ -73,6 +76,27 @@
         }
 
         /// <summary>
+        /// Indicates whether the current <see cref="Row" /> is equal to another <see cref="Row" />.
+        /// </summary>
+        /// <returns>
+        /// true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.
+        /// </returns>
+        /// <param name="other">An object to compare with this object.</param>
+        public bool Equals(Row other)
+        {
+            if(items.Keys.Cast<object>().SequenceEqual(other.Keys.Cast<object>()) == false)
+                return false;
+
+            foreach (var key in items.Keys)
+            {
+                if(items[key].Equals(other.items[key]) == false)
+                    return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
         /// Creates a key from the current row, suitable for use in hashtables
         /// </summary>
         public ObjectArrayKeys CreateKey()
Index: Rhino.Etl.Tests/RowTest.cs
===================================================================
--- Rhino.Etl.Tests/RowTest.cs	(revision 0)
+++ Rhino.Etl.Tests/RowTest.cs	(revision 0)
@@ -0,0 +1,33 @@
+using MbUnit.Framework;
+using Rhino.Etl.Core;
+
+namespace Rhino.Etl.Tests
+{
+    [TestFixture]
+    public class RowTest
+    {
+        [RowTest]
+        [Row(new[] {"a", "b"}, new object[] {1, 2}, new[] {"a", "b"}, new object[] {2, 3})]
+        [Row(new[] {"a", "b"}, new object[] {1, 2}, new[] {"x", "y"}, new object[] {1, 2})]
+        [Row(new[] {"a"}, new object[] {1}, new[] {"a", "b"}, new object[] {1, 2})]
+        [Row(new[] {"a"}, new object[] {1}, new[] {"a", "b"}, new object[] {1, 2})]
+        public void Should_be_different_if_different_columns(string[] firstColumns, object[] firstValues,
+                                                             string[] secondColumns, object[] secondValues)
+        {
+            Row first = FillRow(firstColumns, firstValues);
+            Row second = FillRow(secondColumns, secondValues);
+
+            Assert.IsFalse(first.Equals(second));
+        }
+
+        private static Row FillRow(string[] columns, object[] values)
+        {
+            Row row = new Row();
+
+            for (int i = 0; i < values.Length; i++)
+                row[columns[i]] = values[i];
+
+            return row;
+        }
+    }
+}
\ No newline at end of file
