Automatic Properties

by mgordon 14. November 2007 14:20

I've been exploring some of the new language features that will be available in the coming version of .Net.  I continue to see things that look like they have been borrowed from dynamic languages.  Another to add to the list is automatic properties.  In C#, you'll be able to define properties like this.

public string FirstName { get; set;}

This is functionally equivalent to the following:

private string _FirstName;
public string FirstName
{
    get
    {
        return _FirstName;
    }
    set
    {
        _FirstName = value;
    }
}

This will be a real timesaver for those not using a tool such as CodeRush where creating he above block of code is reduced to three keystrokes (ps<space>) and then typing in the name of the property. 

Now, look at how the equivalent is accomplished in Ruby.

attr_accessor: FirstName

Instead of specifying get; and set;, you specify attr_writer for a write-only property and attr_reader for read-only.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

General | .Net | Productivity | Ruby

Extension Methods

by mgordon 9. November 2007 10:33

With the release of the next version of Visual Studio and the .Net languages, a new feature called Extension Methods will be available.  In a general sense, these allow you to add functionality to classes without having to modify their source including any class in the .Net Framework.  This is a very similar idea to what is offered in a dynamic language such as Ruby, but in the strongly typed .Net languages.

 For example, Ruby has a string type.  If, for some reason, we wanted to add a method to the string class that would return the string wrapped in html that would render the string in a particular color, we could do something like this.

class String
  def to_htmlColor (color)
    "<font color='" + color + "'>" + self + "</font>"
  end
end

puts "fido".to_htmlColor("#AAAAAA")

This would return the string <font color='#AAAAAA>fido</font>

In C#, we can accomplish a similar thing this way.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace testExtensionMethods
{

    class Program
   
{
       
static void Main(string[] args)
        {
           
Console.WriteLine("423".to_i());
           
Console.WriteLine("xxx".to_i());
        }
    }

    public static class Extensions
   
{
       
public static int to_i(this string s)
        {
           
int i;

           
if (!int.TryParse(s, out i))
            {
               
throw new InvalidCastException("String cannot be converted to an integer");
            }
           
return i;
        }
    }
}

Here, I've added a to_i() method to the .Net string class that converts the string value to an integer if it can and throws an exception if it can't.  What triggers the desired behavior is the inclusion of the this keyword in the method signature.  This syntax tells the compiler that the method is to be added to the string type since it follows the this keyword.  The new method can be used on the string class anytime my extension class is in scope.  For example, I could have added my Extensions class in a different namespace and anytime that namespace was included with a using or imports statment, my extension method is available.

Certainly, this is a more brief syntax than int.Parse("423") and feels more natural.  I can recall several situations where I've had to string together commands from various classes in a single statement.  Extension methods could help out with creating convenience methods to replace complicated syntax in these situations.

Scott Gutherie discusses how extension methods were used to add functionality to classes for use with Linq, here.  When the Linq namespaces are included, standard classes are augmented with new functionality that make them easier to use in conjunction with Linq.  In thinking about how I might use these, one idea that came to mind was in a situation where I had a data transport class.  It needs only to be able to contain the data when it's moving between layers, but when it arrives in the business layer from the data layer, it would be nice to be able to add functionality to the class.  This would keep the class nice and tight as it is passed around, but when you need to perform some action on the data contained within, extension methods could be used to add that functionality.  In a way, this technology allows you to have a class function differently based on the "mode" or context it happens to be in at any given time.  Very snazzy!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

.Net | Productivity | Ruby

Ruby in Practice

by mgordon 25. October 2007 13:32

In my current contract, it's the typical story with compressed timelines and pulling off miracles, so I haven't had the opportunity to make use of Ruby for a "real" production application.  However, we're in the midst of doing some work in migrating data from a legacy system into a completely new database schema.  All imagined challenges apply, I assure you.  Part of this exercise is repeatedly bouncing the data against the new schema, applying validations to the data to make sure all the new referential integrity holds true in the new system and reporting on data that isn't fitting into the new system properly.  I took this as an opportunity to apply some Ruby scripting as a means of automating this part of the project.

 Having played with the DBI library a bit before starting, I knew that I wanted to abstract some of the interaction with it away so I wrapped it like so.

  ########## Class to abstract the server connection ##########
  class SqlServer
   
    def initialize(connectionString)
        @dbh=DBI.connect("DBI:ADO:Provider=SQLOLEDB;" + connectionString)
        @dbh["AutoCommit"] = true
    end
   
    def execute(sql)
        statement = @dbh.prepare(sql)
        statement.execute
    end
   
    def fetch(sql)
        statement = @dbh.execute(sql)
        statement
    end
   
    def disconnect
        @dbh.disconnect
    end
  end

I needed to be able to pull fresh data from other databases into my conversion database, so I abstracted that task, as well.

 ########## Class to manage pulling data from one db to another ##########
 class Pull
    def initialize(tableName)
        @table = tableName
        @destination = SqlServer.new("Data Source=server1;initial catalog=database1; trusted_connection=yes")
        @source = SqlServer.new("Data Source=server2;initial catalog=database2; trusted_connection=yes")
    end
   
    def CopyTable
       
        @destination.execute("TRUNCATE TABLE " + @table)
               
        statement = @source.fetch("select * from " + @table)
       
        statement.fetch do |row|
            columns = ""
            values = ""
            insert = ""
           
           
            i = 0
            statement.column_names.each do |name|
                columns += "," + name if columns.length > 0
                columns += name if columns.length == 0
                if row[i].nil?
                    values += ", NULL" if values.length > 0
                    values += "NULL" if values.length == 0
                else
                    values += ", '" + row[i].to_s.gsub("\\", "").gsub("'", "''") + "'" if values.length > 0
                    values += "'" + row[i].to_s.gsub("\\", "").gsub("'", "''") + "'" if values.length == 0
                end
                i = i + 1
            end
           
            columns = "(" + columns + ")"
            values = "values(" + values + ")"
            begin
                insert = "insert into " + @table + " " + columns + " " + values
                @destination.execute(insert)
            rescue DBI::DatabaseError => e
                puts "An error occurred"
                puts "Error code: #{e.err}"
                puts "Error message: #{e.errstr}"
                puts "Error SQLSTATE: #{e.state}"

                puts insert
                exit
            end
        end
        statement.finish
        @destination.disconnect
        @source.disconnect
    end
 end

In my case, all the columns were varchar, so I didn't have to fuss with the format of the data in the insert statements.  With DBI, however, it's possible to get the meta data about each column to decide whether the data needs to be quoted or not.  Now, I needed to be able to pull data about how the load went and any exceptions that were encountered.  That data needed to be saved into CSV files so they could be attached to emails.  The next class was written to do this.

 ########## Class to pull statistic about the load into csv files ##########
 class StatFile
 
    def initialize(connString)
        @server = SqlServer.new(connString)
    end
 
    def GetStats(filePath, sql)
        statement = @server.fetch(sql)
       
        output = File.open(filePath, "w")
       
        statement.fetch do |row|
            output.puts row.to_a.join(",")
        end
       
        output.close
    end
 end

 With the above classes, I was able to script the tasks at hand something like this.

Pull.new("tableName").CopyTable #Copies the table from one db to another

 conversion = SqlServer.new("Data Source=server;initial catalog=database; trusted_connection=yes")
 conversion.do("EXEC ConversionSproc")

 stat.Getstats("c:\\Stat_Files\\exceptions.csv", "select foo1, foo2 from exception_table where error='bad' group by description")

As I've stated before, I'm not planning to use Ruby to put food on the table at this point, but I would like to get some experience using the language if only to get the chance to think about things differently.

 UPDATE:
After using the above scripts a bit, I found that when executing some rather long running stored procedures, I was receiving a timeout.  It was then that I realized there was not way to set the CommandTimout property on the database connection through DBI.  After hours of searching, I was able to gleen enough information to overcome the problem.  I added the following line to the bottom of the initialize method of the SqlServer class:

  @dbh.handle.instance_variable_get(:@handle).setproperty('CommandTimeout', 7200)

Of course, you can specify whatever value you like for the timeout or even parametize the value.

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

Productivity | Sql Server 2005 | Database | Ruby

Powered by BlogEngine.NET 1.1.0.7
Theme by Mads Kristensen

About the author

Name of author Mitch Gordon
Contractor specializing in .Net and other Microsoft technologies.

E-mail me Send mail

Recent posts

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2009

Sign in