• Just a word of warning. This all looks good at first, but you will find it largely unmaintainable in the future. Having to constantly regenerate "wrappers" for all you're procs every time there is one little change to the parameters is daunting. Couple this with the fact that developers cannot even begin to code their business layers until you're done regenerating all the procs makes it very, very unproductive.

    Our company does this today and they've been using this strategy for a couple of years now. It's made developer productivity go from a couple of days to a couple of weeks. Not to mention that the Assembly that they generate all these wrappers in has now become an extra 4 - 10mb of assembly bloat that must be passed around with all applications (I'm not worried about the space, but rather about how much memory is needed to host it). We will soon look into changing this and they are very interested in the strategy I mentioned earlier. The DAL I created to do this was created long before LINQ existed, and having used LINQ myself, I will probably continue using my own because of the pure power that it has over LINQ. For one, I have the ability to Datamap my objects with simple Attributes and can datamap to Columns (including multiple columns) and Parameters. This allows for seemless integration between the Business Objects and DataReaders, DataTables, and Commands.

    Here is what a sample business object might look like. There is no code for datamapping and no direct invocation of Stored Procedures. There's only one requirement that you override the "OnSave" base method. Also, how you fill the object is up to you (Notice the constructors), usually I write a Manager / Director / BusinessService (whatever we're calling them these days) that has all the surrogate methods for my object (ex. ContactDataManager.FillByID(Guid ID)). Take a look at the static method on the class (ex. Contact c = Contact.GetByID(Guid.Empty)).

    [DataMap("dbo.usp_save_Contact", System.Data.StatementType.Insert)]

    [DataMap("dbo.usp_save_Contact", System.Data.StatementType.Update)]

    [DataMap("dbo.usp_delete_Contact", System.Data.StatementType.Delete)]

    public class Contact : BusinessBase

    {

    private string fname;

    [DataMap("FirstName"), DataMap("ContactFirstName"), DataMap("@FirstName")]

    [RequiredRule(), MinLengthRule(1), MaxLengthRule(25)]

    public string FirstName

    {

    get { return (this.fname == null ? string.Empty : this.fname); }

    set {

    if (this.fname == value) return;

    base.OnPropertyChanging("FirstName"); // support for DataBinding and LINQ

    this.fname = value;

    base.OnPropertyChanged("FirstName"); // support for DataBinding and LINQ

    }

    }

    protected overrides OnSave(EventArgs e)

    {

    base.OnSave(e);

    if (e.Cancel) return;

    // Save the object to the Database

    DataService.Update((IUpdatableObject)this);

    }

    public static Contact GetByID(Guid ID)

    {

    DataTable dt = ContactDataManager.GetByID(ID);

    if (dt.Rows.Count == 0) return null;

    return new Contact(dt.Rows[0]);

    }

    // Constructors

    public Contact() : base() {}

    public Contact(DbDataReader Data) : base(Data) {}

    public Contact(DataRow Data) : base(Data) {}

    }

    Example:

    Contact c = Contact.GetByID(Guid.Empty);

    if (c == null) c = new Contact();

    c.FirstName = "John";

    if (!c.Save()) {

    List rules = c.BrokenRules();

    // TODO: Display the broken rules

    // See the Rule Attributes applied to each Property...

    }

    LINQ is nice, as does a lot of this for you. However, if you ever need your business object to come from multiple sources and be fill from two different Column Names (not that uncommon when you work with Tables AND Views or alias columns in Procs), then you will have to create an entirely new set of LINQ objects because they can't map that way (believe me I tried). LINQ is used at best in very simple scenarios to get developers going fast, once you need Enterprise level code, then it severely falls short. I agree, if all you want are the nice little Proc wrapper code it creates, then use it. By the way, the Business Object I wrote above is supported by LINQ and can be also passed into the base "System.Data.Linq.DataContext" and stored in a LINQ ChangeSet for later persistance.