# Saturday, August 22, 2009

I was trying to work though a LINQ to SQL example using IQToolkit as the data context. I found that the LinqDataSource would work fine for reading the data.  But when attempting to update the data an exception was raised indicating the data context did not extent System.Data.Linq.DataContext.  So to finish up the example, I needed to create a custom LinqDataSource for IQToolkit.  After a little inspection using Reflector, I found that I just needed to create two sub-classes.

The first class that needed to be created was a sub-class of LinqDataSourceView:

using System;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
using IQToolkit;
 
namespace IQToolkitContrib.Web {
    public class DataSourceView : LinqDataSourceView {
        private LinqDataSource owner;
 
        public DataSourceView(LinqDataSource owner, string name, HttpContext context)
            : base(owner, name, context) {
            this.owner = owner;
        }
 
        /// <summary>
        /// Make sure that the data context has a property that implements IEntityTable
        /// </summary>
        protected override void ValidateContextType(Type contextType, bool selecting) {
            if (!selecting && contextType.GetProperties().Where(p => p.PropertyType.GetInterface("IEntityTable") != null).Count() == 0) {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "The data context used by IQToolkit-DataSourceView '{0}' must have an IEntityTable Property when the Delete, Insert or Update operations are enabled.", this.owner.ID));
            }
        }
 
        /// <summary>
        /// Make sure that the table implementes IEntityTable
        /// </summary>
        protected override void ValidateTableType(Type tableType, bool selecting) {
            if (!selecting && (!tableType.IsGenericType || tableType.GetInterface("IEntityTable") == null)) {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "The table property used by IQToolkit-DataSourceView '{0}' must extend IEntityTable when the Delete, Insert or Update operations are enabled.", this.owner.ID));
            }
        }
 
        protected override void DeleteDataObject(object dataContext, object table, object oldDataObject) {
            ((IEntityTable)table).Delete(oldDataObject);
        }
 
        protected override void UpdateDataObject(object dataContext, object table, object oldDataObject, object newDataObject) {
            ((IEntityTable)table).Update(newDataObject);
        }
 
        protected override void InsertDataObject(object dataContext, object table, object newDataObject) {
            ((IEntityTable)table).Insert(newDataObject);
        }
    }
}

The second class that needed to be created was a sub-class of LinqDataSource:

using System.Web.UI.WebControls;
 
namespace IQToolkitContrib.Web {
    public class DataSource : LinqDataSource {
        protected override LinqDataSourceView CreateView() {
            return new DataSourceView(this, "DefaultView", this.Context);
        }
    }
}

After building these two classes in a separate assembly, I was able to use the DataSource as I would any other custom server control.

8/22/2009 12:02 PM Eastern Daylight Time  #    Disclaimer  |  Comments [0]  | 
 # Wednesday, August 19, 2009

The following example is a quick proof of concept simply showing how to view the Customer table from the Northwind.dbc.

  1. Create a new WebSite.
  2. Add references to IQToolkit.dll and LinqToVfp.dll
  3. Add a Northwind connection string setting to the web.config
    <connectionStrings>
        <add name="northwind" 
             providerName="System.Data.OleDb" 
             connectionString="Provider=VFPOLEDB.1;Data Source=**Your Path**\Northwind.dbc;"/>
    </connectionStrings>
  4. Add a new class:  Customer.cs
    public class Customer {
        public string CustomerId { get; set; }
        public string CompanyName { get; set; }
        public string ContactName { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string Region { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
        public string Phone { get; set; }
        public string Fax { get; set; }
    }
  5. Add a new class:  Northwind.cs
    using System.Configuration;
    using IQToolkit;
    using LinqToVfp;
     
    public class Northwind : AVfpDatabaseContainer {
        public Northwind()
            : base(ConfigurationManager.ConnectionStrings["northwind"].ConnectionString, null) {
     
            // this will make it so that all command will be logged to the Output windoww
            this.Provider.Log = VfpQueryProvider.CreateDebuggerWriter();
        }
     
        public IEntityTable<Customer> Customers {
            get { return this.Provider.GetTable<Customer>("Customers"); }
        }
    }
  6. Modify Default.aspx to include to following in the div tag:
    <asp:GridView ID="mainGrid" 
                  runat="server" 
                  DataSourceID="LinqDataSource1" 
                  AllowPaging="True"
                  AllowSorting="True" />
     
    <asp:LinqDataSource ID="LinqDataSource1" 
                        runat="server" 
                        ContextTypeName="Northwind"  
                        TableName="Customers" />
8/19/2009 7:07 AM Eastern Daylight Time  #    Disclaimer  |  Comments [0]  |