Phil posted on December 11, 2009 03:06

Here’s a class that’ll make your life easier when you want to deal with saving information in cookies on your user’s browser. Everyone needs a wrapper class for all those external data-stores – session, cookies, file system, web.config and app.config, registry, log files, etc. Here’s a class usable in ASP.NET Web Forms and ASP.NET MVC.

Wrapper Class

Here’s a static class that you can simply include in your web project, and refer to its static properties to get to your cookies. Any and all simple datatypes can be used, and heck, even serialized versions of your POCO objects can be saved/retrieved here. Image if you wanted to save those shopping cart items, a collection of user prefs, or whatever, you could simply override the .toString() method in your custom class.

Just Make Properties

The key pattern here is that you purposefully create new properties for each piece of data that you want to save/retrieve. This solves the problem of:

  • having to remember strings all over your project.
  • ensuring no duplicates exist – imagine if multiple developers created a defect by using the same string indexer for their cookie, and ended up stomping each other’s value?
  • typos in cookie names.

Instead, the data access cookie-retrieval is done through named properties. This solution solves all those potential problems. Here’s a peek at one of these properties.

public static string UserFullName
{
get { return GetCookieVal(CookieItem.UserFullName); }
set { UpdateCookieVal(CookieItem.UserFullName, value, 365); }
}

Enums Help

With the aforementioned ‘remembering strings’ problem, the pattern that this class uses relies internally on an enum to handle the naming of the value in the cookie. The enum will boil down to an integer, but really we don’t care what the key’s is actually stored as in the cookie. We really only care to access/read/save the values constantly and easily from our calling code.

Download

Download the cookie class, or copy/paste from below. You can see that I pre-loaded it with some amusing properties for your entertainment!

Be sure to change the ApplicationName const at the top.

Special thanks to Special-K!

using System;
using System.Web;

namespace MyNamespace
{
public class Cookies
{
private const string ApplicationName = "MyCoolApplication";

private enum CookieItem
{
UserGuid,
UserFullName,
UserLoginExpiry,
UserHadForBreakfast,
UserTimezone
}
/**************
All cookie values are accessible by public static methods.
No typos/duplicates are possible from calling code!
**************/

public static string UserFullName
{
get { return GetCookieVal(CookieItem.UserFullName); }
set { UpdateCookieVal(CookieItem.UserFullName, value, 365); }
}

public static Guid UserGuid
{
get { return new Guid(GetCookieVal(CookieItem.UserGuid)); }
set { UpdateCookieVal(CookieItem.UserGuid, value.ToString(), 365); }
}

public static DateTime UserLoginExpiry
{
get { return DateTime.Parse(GetCookieVal(CookieItem.UserLoginExpiry)); }
set { UpdateCookieVal(CookieItem.UserLoginExpiry, value.ToString(), 365); }
}

public static string UserHadForBreakfast
{
get { return GetCookieVal(CookieItem.UserHadForBreakfast); }
set { UpdateCookieVal(CookieItem.UserHadForBreakfast, value, 1); }
}

private static string GetCookieVal(CookieItem item)
{
HttpCookie cookie = GetAppCookie(false); //get the existing cookie
return (cookie != null && (cookie.Values[item.ToString()] != null)) //value or empty if doesn't exist
? cookie.Values[item.ToString()]
: string.Empty;
}

private static void UpdateCookieVal(CookieItem item, string val, int expireDays)
{
//get the existing cookie (or new if not exists)
HttpCookie cookie = GetAppCookie(true);

//modify its contents & meta.
cookie.Expires = DateTime.Now.AddDays(expireDays);
cookie.Values[item.ToString()] = val;

//add back to the http response to send back to the browser
HttpContext.Current.Response.Cookies.Add(cookie);
}

private static HttpCookie GetAppCookie(bool createIfDoesntExist)
{
//get the cookie or a new one if indicated
return HttpContext.Current.Request.Cookies[ApplicationName] ?? ((createIfDoesntExist) ? new HttpCookie(ApplicationName) : null);
}

}
}


Posted in: c# , asp.net , best practices , code blowout , development  Tags:
Actions: E-mail | Permalink | Comments (0) |
Phil posted on November 5, 2009 05:07

Perhaps you’ve got a collection of objects that you want ordered/sorted. I recently did. Perhaps you want them displayed in a non-deterministic manner or sorted randomly each time you write to an HTML view or otherwise consume that collection. Indeed, I did. (OK, lame shtick over…)

Randomize()

So imagine we’re working with a List of Customers.

data

Problem being, we don’t really have anything non-deterministic to work with. We could do this in SQL Server:

SELECT *
        ,(sin(Cust.ID * rand())) AS R
FROM Cust
ORDER BY R

This though, puts your presentation logic in your data tier. Maybe you don’t care, maybe it’s not a big price to pay. I wanted to take it up to the presentation tier and do this sorting right before binding or writing these objects to the page.

Taking the lead from Bruno Silva, I immediately realized this was the seed of the algorithm that I was looking for. Here’s my modification of Bruno’s algorithm:

   Random r = new Random(); 
   myCusts.OrderBy(x=>(r.Next())); //bind this, or use in a foreach

The call to r.Next() is obviously the key. Each object as it is evaluated in the OrderBy() will get a new random number associated with it. Celebrate good times!

Turn It Into an Extension Method

I haven’t written much here about how much I love extension methods in the .NET CLR 3.0. I can’t count the number of times that I’ve created a static ‘utility’ method that did something like this:

  • take in an object of some kind.
  • modify it.
  • return it back to the caller.
  • caller reassigns the return back into the object that it calls.

Rather than the above, I’ve created an extension method that I’ll be able to call whenever for any collection that implements IEnumerable. It’s trivial then to write the extension method for IQueryable.

ExtensionMethod I’ve submitted my Randomize() extension method over at ExtensionMethod.net. What a great site, by the way, kudos to those guys for taking user submissions and helping grow the use of this feature in .NET.

 

http://extensionmethod.net/Details.aspx?ID=236

public static IEnumerable<t> Randomize<t>(this IEnumerable<t> target)
   {
       Random r = new Random();
       return target.OrderBy(x=>(r.Next()));
   }


Posted in: development , c# , linq , extension methods  Tags:
Actions: E-mail | Permalink | Comments (0) |
Phil posted on November 2, 2009 01:10

I recently had the privilege of working on a contract where the main goal of the project was to port/convert the web project and associated assemblies (business and data layers) from one .NET language to another. The other tasks were around fixing a handful of defects, and adding a few bits of functionality. The project was hard-capped at a set quoted number of hours, so there was little room for error.

The solution consisted of three .NET 3.5 projects:

  • ASP.NET web project – this project had roughly 10 pages and a handful of helper classes in the App_Code directory. This project already had VB as its language.
  • Business Layer Assembly – 6 classes brokering access to the data layer. Very much pass-through code with not a lot of business logic in between the web layer and data layer. There were moderate amounts of looping and updating of the business object properties.
  • Data Layer Assembly – the DL included the matching DL classes for each of the 6 classes above. The most challenging (code for the converter here was the Linq-To-Sql code.

Sizing Up the Task

The largest part of the project for me was the conversion task. All told, the conversion/translation involved:

  • 12 .cs files
  • ~55 methods
  • ~500 lines of code

I had previously figured the smartest way to spend my time was not rewriting code by hand. If there’s anything a developer should be good at, it’s evaluating and choosing to use the right tool for the job. That’s a major part of your job as a developer!

Enter the Telerik Batch Converter Tool

A quick Bing search brought me to a few options: online-in-the-browser-cut-and-paste style, or full file upload.

I first noticed that Telerik had a batch converter tool. This allows the user to upload a handful of source code files, and the converter will do its magic on the server. This was right up my alley, as it meant that I didn’t have to laboriously open each code file, copy, paste, and make a new source code file.

Telerik Batch Code Converter Upload

The initial load of the page shows the user 3 input boxes where you can browse to the location of your code file. Obviously for those ASP.NET web projects needing conversion, you don’t need to upload your .aspx files, but rather your code-behind files. This particular project was using code-behind files, rather than inline <script>.

Aside: It’s amazing to me that some developers are using <script> tags to hold their code which belongs in a code behind  Page.aspx.cs or .vb file. Obviously it’s a style or configuration issue, but to me it just feels wrong. I like the separation of .NET code and HTML markup. Perhaps it’s just a side effect of trawling the web for source code, and people are choosing to format their .aspx to include code within, instead of posting separate files.

Back to the task. The process is easy:

  • Browse one-by-one for the files you need converted. Make sure to remember to pickup your Linq-To-Sql’s .designer.vb or .cs class. That’s the file where your SQL Server tables are mapped to POCO [Plain Old CLR Objects ;) ]
  • Upload, Convert and Download a .zip containing the artifacts of the conversion. Included are all the converted files, and a Report.txt file.

Telerik Batch Code Converter Done

Results & Conversion Report

The real answer you’re looking for is right here: the results of the conversion with the Telerik tool, for me, were 100%. Absolutely no problems were had in compiling a new project with these new files added to it. I can’t believe it was so easy. Here’s the report that Telerik included in the .zip (irrelevant or repetitive bits snipped):

Conversion Error Report (Created [datetime])

Every time a possible conversion problem is located, the file name, problem severity , and problem description are recorded. There are three levels of severity:

    Warning    = code will convert and will likely work, but conversion may need manual improvement
    Minor    = code will convert, but it will likely need manual correction to work
    Major    = code will not convert. It must be modified before used with converter

There are also general issues to remember when converting web sites:
    - Events connected with the Handles syntax in VB will not work in C#. Events must be connected in code or in the control markup.

Report Details:
================================================
1: TEST.designer.cs    Minor    Your region may not convert from C# to VB if quotes have not been used to name the region. Make sure       region name is surrounded in quotes before using code.
2: TEST.designer.cs    Minor    Your region may not convert from C# to VB if quotes have not been used to name the region. Make sure       region name is surrounded in quotes before using code.

End Report (11 total matches)

Easy & Accurate Results

I can’t believe it was so easy to convert the code. It really meant that I could spend more time ADDING VALUE to the project by way of adding features and fixing defects than by the drudgery of converting source between languages. The price to pay for the Telerik online batch tool was the included comments at the bottom of each source file. That’s an easy price to pay! Can I say now a BIG THANK YOU to Telerik, NRefactory & SharpDevelop, and Todd Anglin @ Telerik for making this tool free and available for the world at large!

TelerikBatchCodeConverter_Comments

Stitching your Converted Files Back Into a Project & Solution

The tricky work is to then take the output of the converter and create a new project. For each of the assembly projects, I:

  • copied all the reusable non-.NET files from the old solutions - *.xml, *.config, etc.
  • made new .vbproj projects in Visual Studio
  • for the web project, Add Existing Files –> Select all your converted files.

For those converting a web project, just create a new Web Project. For each of your pages, modify your .aspx  to have its Page directive to have the appropriate configurations:

<%@ Page Language="VB" MasterPageFile="~/SomeMaster.master" CodeFile="SomeFile.aspx.vb"

Then do the same Add Existing Files routine for all your converted .aspx.vb or .cs files.

Quick Online .NET VB and C# Converters

In some cases, you’ll find snippets online (yes, the bathroom wall of code) where you actually like the snippet, but rather want it in the language of your choice. I recently searched for and used both these tools when needing to convert a large snippet of VB to C#.

Try DeveloperFusion’s online code conversion tool - http://www.developerfusion.com/tools/convert/vb-to-csharp/

Telerik’s Code Converter is of course, likely to be mostly used for its quick online code converter - http://converter.telerik.com/


Posted in: linq-to-sql , c# , vb , shortcuts , best practices  Tags:
Actions: E-mail | Permalink | Comments (0) |
Phil posted on October 12, 2009 05:43

Damien Guard was nice enough to blog about changes coming to L2S in VS 2010. Rather, the changes are coming in the .NET Framework 4.0.

The whole rumor within the development community/blogs about "Linq To Sql is being unsupported, Entity Framework is the new coolness" was just plain wrong, I believe. Microsoft is too big, and has too many projects on the go. They'll gauge the momentum of both technologies. Have you heard Damien as a guest on Herding Code Episode 50? In this blog post, Damien says that the focus for Microsoft will be on EF, and that's fine. L2S is definitely not dead!

I still believe that if you're needing an ORM, and working with SQL Server, then use Linq To Sql. I've tried EF, and it worked fine. I've ended up with 4 projects using L2S, and haven't found any real need for EF.

Welcome Defect Fixes in coming in .NET 4.0 for Linq-To-Sql

For me, the most interesting changes within Damien's post are:

* Contains() with enums automatically casts to int or string depending on column type

* String.StartsWith(), EndsWith() and Contains() now correctly handles ~ in the search string (regular & compiled queries) - Here's a small defect. I've not needed to search for tildes very much, but I decided to give it a shot just in case! It's true, the behavior is just as described!

tilde-2

tilde 

 

* Now detects multiple active result sets (MARS) better - I am not the heaviest user of L2S, and definitely haven't needed to specify MARS myself. Here's the MultipleActiveResultSets defect as reported on MS Connect. It's a simple issue where the connection string property "MultipleActiveResultSets" is only picked up when CamelCased exactly as shown above. Any deviation will ignore the option!

* DeleteDatabase no longer fails with case-sensitive database servers - Interesting that this functionality even exists. I had to research this method - DataContext.DeleteDatabase(). I can't recall actually seeing it in the Intellisense method list, but indeed it's there! Most blogpost or articles that I read in that 5 minute span were talking about using this method for tear-down during "Unit Testing". I'd call that integration testing, and ill-informed as well. Unit tests should not include databases!

DeleteDatabase

* VarChar(1) now correctly maps to string and not char - This one has bitten me before. The column was called Gender. Of course it was storing M, F, T, or U for unknown. The core of the problem was that some rows were having a blank stored in this field, rather than null. StackOverflow to the rescue! http://stackoverflow.com/questions/1190328/linq-to-sql-exception-string-must-be-exactly-one-character-long. After some thought, I'd agree that storing this value as char(1) would be semantically more correct, more performant, and consume just one byte per tuple.

varchar

len zero 

* Decimal precision and scale are now emitted correctly in the DbType attributes for stored procedures & computed columns - I couldn't reproduce this defect, and perhaps I misunderstood.  I defined a decimal(18,5) attribute on the table, and L2S brought it back without any problems. Then I realized the key to this defect was probably the 'computed' bit. So I went and created a simple decimal return type. I ran the query, and still no defect.

computeddecimalsOK

Then I clued in - the defect was under the Linq To Sql Designer heading. So upon further inspection, here's the defect in the myL2S.designer.cs. The return type is calculated as decimal(0,0). Ouch! :)

  decimalzero

* Foreign key changes will be picked up when bringing tables back into the designer without a restart - This defect has hit me a few times as well. It appears as such:

  • Edit a FK in SQL Server. If you've got an open L2S file, deleting + dragging and dropping those tables back onto the L2S surface DO NOT show your FK changes.
  • Clicking the Refresh button in Server Explorer doesn't help.
  • The only solution is to close your L2S file, and re-open.

* Changing a FK for a table and re-dragging it to the designer surface will show new FK’s - this is very much related to the item above.

* Opening a DBML file no longer causes it to be checked out of source control - this has appeared to me a few times. Simply opening/viewing the L2S file creates a 'check out'. Nothing earth shattering here, and glad to see this is fixed.

* Can edit the return value type of unidentified stored procedure types - This feature is great! It's very helpful when you've got a sproc that shapes data just the exact perfect way that you'd like to show on a custom report. Perhaps you're binding to an asp:GridView or including as part of an MVC FormViewModel. The normal course of action is:

  • Create your sproc to shape your data as you like

    Sproc-To-Custom-Object

  • Drag a sproc onto the Methods section of the L2S designer.
  • Try change its return type to a class you've created solely for the purpose of binding

  • Oops, it's locked!

    locked

    The work around is a bit time-consuming. You have to:

    • open up the myL2S.designer.cs file

    • find your method marked with the attribute containing your sproc name

    • replace the default return type int with ISingleResult<T> - in my simple example here, it's ISingleResult<CustomerReport>

      modify dbml

    The frustrating bit here is that this behavior isn't predictable (to me at least). I CONSTANTLY have to go through this process to properly set the return type of 2 sprocs in one particular project. This defect fix in particular by Microsoft will be welcome!


Posted in: linq-to-sql , c# , microsoft  Tags:
Actions: E-mail | Permalink | Comments (0) |

On two recent projects, I've had the need to write out the properties of multiple custom entities. The example here will be around the venerable Customer class. Let's pretend that a requirement would be to send an email each time a customer makes an order to a support rep in your company. Yes, we'll be logging the order to the database, but the value-add here is that the recipient of the email will receive a link to the order, plus all the details of the customer and order included in the email.

So we need to take an object, iterate through its properties and their values, and put into a string for the body of an email.

The first thought might be: "just loop through each property and write it to the email body". That's fine, but as soon as you add a property in the future, you need to remember to change the emailing code. That's not helpful for the developer needing to maintain this application. Let's look at the Reflection namespace in the .NET framework.

Reflection in .NET

Reflection lets you programmatically find out information about types in your assemblies at runtime. Using classes in the System.Reflection namespace, you can learn details of an class's methods & properties. In the topic at hand, we're interested in the names, values, and datatypes of properties. You could possibly use reflection to get info at runtime about a method's parameters.

Override Customer.ToString()

The Customer class needs its own ToString() method overridden. Here's the class:

 
using System.Reflection; 
using System.Text;
 
public class Customer{
    
    public string Name{ get; set; } 
    public string Email { get; set; }
    public string Address { get; set; } 
    public string City { get; set; } 
    public string State { get; set; } 
    public DateTime JoinDate { get; set; }
        
    public override string ToString() {
    
        StringBuilder personString = new StringBuilder(); 
    
        foreach (PropertyInfo pi in this.GetType().GetProperties()) {
            //get the name of the property and its value. 
            personString.AppendLine(string.Format("{0}: {1}", pi.Name, pi.GetValue(this,null))); 
        } 
 
        return personString.ToString(); 
    }
} 

 

Use It!

 
Customer cust = new Customer{
    Name = "Mike",
    Email = "some@dot.com",
    HomeAddress = "1 Some Street",
    State = "ZZ"};
 
string customerOuput = cust.ToString(); //now put this in your email body!
 
Console.WriteLine(customerOutput);
 
/* Console will show:
Name: Mike
Email: some@dot.com
HomeAddress: 1 Some Street
City: 
State: ZZ
JoinDate: 
*/

 

Consider This…

There are a few things to consider with this implementation:

  • collections aren't handled well.
  • complex datatypes aren't either.
  • consider customizing your implementation to include special formatting for DateTimes.
  • what happens when you want the output to have a well-formatted output for a property like HomeAddress. We'd probably want it to show as "Home Address".
  • consider handling null values better than writing "null".

Wrap Up

I know this will save developers time in two ways:

  1. Not having to iterate manually through X properties to build your string for email. That'll scale depending on the number of properties and your adeptness at Ctrl-C, Ctrl-V.
  2. When you add a new simple property, you will NOT have to adjust anything for it to show in the .toString() method.

How are you using System.Reflection?

Posted in: c# , development , code blowout , .net framework  Tags:
Actions: E-mail | Permalink | Comments (0) |

Today's Dreaded Exception: Data at the root level is invalid.

Found a problem recently when serializing a custom object.  Here's what I was working with. Warning: this is the bathroom wall of code version. Do not copy/paste this into production.

public static XmlDocument SerializeToXmlDoc(Object obj) 
{ 
 try 
    { 
        XmlDocument xmlDoc = new XmlDocument(); 
        string xmlString =  SerializeIt(obj);             
        xmlDoc.LoadXml(xmlString); 
        return xmlDoc; 
    } 
    catch (Exception e) {   return null; } 
} 
 
public static string SerializeIt(Object obj) 
{ 
    try 
    {     
        MemoryStream memoryStream = new MemoryStream(); 
        XmlSerializer xs = new XmlSerializer(obj.GetType()); 
        XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8); 
        xs.Serialize(xmlTextWriter, obj); 
 
        memoryStream = (MemoryStream)xmlTextWriter.BaseStream; 
 
        string xmlString = UTF8ByteArrayToString(memoryStream.ToArray()); 
        return xmlString; 
    } 
    catch (Exception e) { return null; } 
} 
 
private static string UTF8ByteArrayToString(byte[] characters) 
{ 
    UTF8Encoding encoding = new UTF8Encoding(); 
    String constructedString = encoding.GetString(characters); 
    return (constructedString); 
} 

The problem that was that as I passed one of my custom objects to it, I'd get this exception:
Data at the root level is invalid. Line 1, position 1.

Fine, root level… got it. Let's take a peek at what's actually trying to be loaded.

Wait, What The…?

Here's the kicker: there was a funny null/something character at the beginning of the string, and therefore, my XmlDoc couldn't successfully execute the LoadXml method. Confessional: I scraped this method from the interwebs and its bathroom wall of code. I tweaked it to suit my needs. I figured it was ready for ANY kind of POCO object. Guess not. I have hit the 10% case where it didn't work well. Well, let's fire up the Text Visualizer and figure out why that string isn't loading into an XmlDocument properly.


Text Visualizer Visual Studio xml string

Hmm. That's funny. What is that?! Turning to the Immediate Window didn't give any real answers as to the value of that unknown/bad character.

immediate window Visual Studio 2008
Hmm. Looks blank. I then copied that value right from the Immediate Window, pasted into Notepad, it comes out as a question mark. Nice! Here's the direct paste:

?xmlString.Substring(0,1)
"?"

Solved!

You could go down all kinds of kludgey roads and try to replace the first character if it's not angle bracket "<", or try and trim null chars, etc.

Turns out that a StringWriter will do the job well in this case. No more null character leading to a failed load of the string.
(via the bathroom wall of code at http://asp.net2.aspfaq.com/xml-serialization/simple-serialization.html)

public static string SerializeIt(Object obj) 
{ 
    try 
    {               
        XmlSerializer serializer = new XmlSerializer(obj.GetType()); 
        StringWriter sw = new StringWriter(); 
        serializer.Serialize(sw, obj); 
        sw.Close(); 
 
        // get the Xml as a string 
        string xmlString = sw.GetStringBuilder().ToString(); 
 
        return xmlString; 
    } 
    catch (Exception e) { return null; } 
}

 

 

 

The MemoryStream algorithm worked well for some of my POCO objects, but not for another.


Posted in: c# , visual studio , xml , serialization  Tags:
Actions: E-mail | Permalink | Comments (0) |

So your application needs to send emails to stakeholders/customers/admins/managers. You know the kind of emails:

  • password reminders,
  • account balances,
  • reminders & status updates
  • confirmations of all sorts

Typically my development routine consisted of something like this:

  1. Write a template email. String constants with placeholders, etc. Dear [FirstName] [LastName],
  2. Read all appropriate details from a data-store. You know, the things specific to the recipient of the email. Replace [FirstName] [LastName] with real names, or a link specific to their account to reset their password, etc.
  3. Write the email sending business logic. System.Net.Mail and all the goodness within. Attachments, BCC, SMTP, all those good things provided by that namespace. (Thank you Microsoft, for helping us forget CDONTS.)
  4. Put in your own email address to receive the unit tests and integration tests.
  5. Brace for the email flood into your mail client.
  6. Context switch between the mail client and development IDE. More back and forth for you!

New Tool in the Toolbox – Already Built into the .NET Framework!

While testing, you can have emails sent to a directory instead of being sent to SMTP server. Simply put this in your web.config:

<system.net> 
    <mailSettings> 
        <smtp deliveryMethod="SpecifiedPickupDirectory"> 
            <specifiedPickupDirectory pickupDirectoryLocation="c:\SomeEmailDirectory\" /> 
        </smtp> 
    </mailSettings> 
</system.net> 

 

So What?

So how much time does it really save you? It’s negligible, really, when your mail server is on the LAN. If you are working with an SMTP server that is unreliable, slow, or keeping accounting on mail count/charging for bandwidth, the seconds per sent email can add up.

No matter about SMTP servers… good, bad or ugly. You could monitor a directory with the .NET FileSystemWatcher to watch for newly dropped email files, and then open them automatically!

Imagine, your unit or integration tests create a new email to be sent, and another dev tool (using FileSystemWatcher) can automatically ShellExecute it for you. That saves you the time of switching to the directory, double clicking the newly created email, and then getting on with the work of checking for correctness.

Credit

Yep, this StackOverflow question keeps on giving!

http://stackoverflow.com/questions/54929/hidden-features-of-asp-net


Posted in: asp.net , c# , development , email , shortcuts , testing  Tags:
Actions: E-mail | Permalink | Comments (0) |
Phil posted on April 26, 2009 01:23

Taking the advice of Scott Hanselman today. It's a code garage sale. Everything of worth (you be the judge!) must be opened up and freed for WAY below cost.

SQL Server ADO Abstractor/Wrapper

never write a line of ADO.NET setup code again!

The first offering is a .NET class that you can reference in any project that needs to call SQL Server stored procedures. It takes care of spinning up the ADO.NET objects and closing them (mostly) when appropriate.

Use it to:

  • ExecNonQuery
  • ExecScalar
  • ExecDataReader
  • ExecDataSet

All you've got to do is supply it with:

  • a connection string (as managed by your own datalayer and/or app.config. Hardcode a string into it, go ahead, see if anyone cares),
  • a stored procedure name
  • any parameter names and values that you need.

Another great feature here is that this class implements the IDisposable interface. This means you can use it with the Using statement/construct, and it will go out of scope when execution steps out of the Using statement/construct. This saves you a line or two of code.

Here's some sample code showing how to use it:

C#

   1:      // run a non-query stored procedure
   2:     try{                
   3:          using (SqlAdoAbstractor db = new SQLDataHelper(someConnectionString))
   4:          {
   5:              db.AddParam("@MyNumericIdentifier", 1);
   6:              db.AddParam("@MyString", "Hello World");
   7:          
   8:              db.ExecNonQuery("MySproc");
   9:          }
  10:      }
  11:      catch (Exception ex) { throw; }
  12:              
  13:      // get a datareader
  14:     try{                
  15:          using (SqlAdoAbstractor db = new SQLDataHelper(someConnectionString))
  16:          {
  17:              db.AddParam("@SomeNumericIdentifier", 1);    
  18:          
  19:              SqlDataReader dr = db.ExecReader("ListAllEmployeesByRegionID");
  20:              
  21:              //iterate through your datareader as necessary
  22:              while (dr.Read()){
  23:                  //dr["EmpID"].ToString();
  24:              }
  25:              dr.Close(); //you must close the open reader 
  26:          }
  27:      }
  28:      catch (Exception ex) { throw; }
  29:      

VB

   1:  Using help As SqlAdoAbstractor = New SqlAdoAbstractor(someConnectionString)
   2:          help.AddParam("@MyNumericIdentifier", 1)
   3:          help.ExecNonQuery("MySproc")
   4:   
   5:      End Using
   6:   
   7:   
   8:      Using help As SqlAdoAbstractor = New SqlAdoAbstractor(someConnectionString)
   9:          help.AddParam("@MyNumericIdentifier", 1)
  10:          Dim dr As SqlDataReader = help.ExecReader("MySproc")
  11:   
  12:          While dr.Read
  13:              'dr("EmpID")
  14:          End While
  15:          dr.Close 'you must close the datareader yourself
  16:      End Using

Posted in: ado.net , c# , code blowout , datalayer , vb  Tags:
Actions: E-mail | Permalink | Comments (3) |