Skip to main content

Adapting DataRow to IDataRecord

You can find code for adapting a DataRow to the IDataRecord interface all over the place. One scenario in which this might be useful is [when the dregs of coding society are forced to perform] mapping the results of a database call to a custom object with the results sometimes coming back as a DataSet and sometimes as a DataReader.

IDataRecord has a lot of members that you probably wouldn’t use, simply because they are for retrieving strongly-typed values from the record based on numeric index. You’re probably doing these conversions manually and getting the values by named index. If that’s the case, why not constrain the consumption of these types with the following interface:

public interface IIndexedDataRecord
{
    object this[string name] { get; }
}

and these adapters:

public class DataReaderAdapter : IIndexedDataRecord
{
    private readonly IDataReader reader;

    public DataReaderAdapter(IDataReader reader)
    {
        this.reader = reader;
    }

    public object this[string name]
    {
        get { return reader[name]; }
    }
}

public class DataRowAdapter : IIndexedDataRecord
{
    private readonly DataRow row;

    public DataRowAdapter(DataRow row)
    {
        this.row = row;
    }

    public object this[string name]
    {
        get { return row[name]; }
    }
}

I think if I were designing a data layer that used plain ADO.NET (which I would never do), I would use this simplified interface. Of course, the drawback is there would be a need to adapt both IDataReaders and DataRows when passing them to consuming methods, whereas only DataRows would need to be adapted when consuming methods are programmed to the IDataRecord interface.

Comments

Keith said…
Thanks for the great tip. This is much cleaner than having to use a DataRow-to-IDataRecord converter.

Popular posts from this blog

Who I'm Is

I am a junior .NET developer currently working in Chicago, IL. I am starting this blog in order to enhance my knowledge of programming subject matter. Hopefully, someone else will be helped along the way. This first post will probably be edited soon...

Stubbing Static Methods with PostSharp

TypeMock uses the Profiler API to allow mocking, stubbing, etc. of classes used by code under test. It has the ability to handle sealed classes, static classes, non-virtual methods, and other troublesome-yet-oft-encountered scenarios in the world of unit testing. Other frameworks rely on proxies to intercept method calls, limiting them to be able to only fake virtual, abstract, and interface members. They also rely on dependecy injection to place the proxies as the concrete implementation of calls to the abstracted interface members. Anyone working with a legacy codebase is bound to run into static method calls (especially in the data access layer), dependencies on concrete types with non-virtual methods, and sealed class dependencies (HttpContext anyone?). The only way to unit test this without refactoring is with TypeMock. I've never used TypeMock, and I'm sure it's a great product, but it's not free. I decided to spike some code to see if I could solve the prob...

Strongly-Typed Property Constraints in Rhino Mocks

UPDATE: As I suspected, this functionality was right in front of my face – it’s called PredicateConstraint in Rhino Mocks. I also realize that I managed to completely ignore the existence of Predicate<T> in the framework, and write my own predicate delegate. Hey, I was on a roll. Rhino Mocks has a PropertyConstraint class that allows you to check the values on properties of objects passed into the method as part of the verification for that method being called. Unfortunately, the name of the property is specified as a string, which means the benefits of strong-typing that Rhino Mocks is normally so good at preserving are lost. Here’s an example (using Rhino Mocks 3.3 and .NET 2.0): [Test] public void Main_Form_Should_Show_Start_Panel_On_Load() { MockRepository mockRepository = new MockRepository(); IMainFormView mockView = mockRepository.DynamicMock<IMainFormView>(); IEventRaiser loadEventRaiser = GetEventRaiserFor(delegate { mockView.Load += null; });...