关键
1、在数据层创建 强类型的DataSet和TableAdapter,TableAdapter查询可以使用现有的存储过程。注:直接把表或存储过程拖进来会自动创建TableAdapter
2、中间层的类用[System.ComponentModel.DataObject]声明为数据组件,CRUD方法分别对应[DataObjectMethod(DataObjectMethodType.Insert)],[DataObjectMethod(DataObjectMethodType.Select)],[DataObjectMethod(DataObjectMethodType.Update)],[DataObjectMethod(DataObjectMethodType.Delete)] 
3、web层使用ObjectDataSource展现数据,ObjectDataSource就相当于一个代理。ObjectDataSource只是查找具有匹配的参数名称的方法,它不会使用参数的 Type 或 Size,而只是对参数的名称进行匹配
4、其它
 ·有ConvertEmptyStringToNull属性,默认是true。另外还有Direction属性
 ·注意的这几个属性NullDisplayText,HtmlEncode,ApplyFormatInEditMode,InsertVisible,DataFormatString,ReadOnly
 ·DataKeyNames有多个值的话用“,”分隔,用绑定的话给其加一个“PropertyName”属性,值类似如下“SelectedDataKey.Values[0]”
 ·关于绑定:简单属性<%# custID %>;集合;表达式<%# ( customer.FirstName + " " + customer.LastName ) %>;方法<%# GetBalance(custID) %> 
 ·<%# Eval("field1") %> 和 <%# Bind("field1") %>,Eval是单向绑定,Bind是双向邦定
 ·有一个OldValuesParameterFormatString属性一般不用,不过如果要处理乐观并发之类的就会用到。当该属性的值为“original_{0}”的时候“original_参数名”则为初始值
 ·还有一些如编程方式给参数赋值,错误处理,得到返回值之类的请看源码
示例
相关存储过程和数据层略,见源码
单例模式的实现
App_Code/Singleton.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
/**//// 
/// Singleton 的摘要说明
/// 
public class Singleton where T : new()
{
 public static T Instance
 {
 get { return SingletonCreator.instance; }
 }
 class SingletonCreator
 {
 internal static readonly T instance = new T();
 }
}
中间层代码
App_Code/Test.cs
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using TestDatabaseTableAdapters;
using System.ComponentModel;
/**//// 
/// Test 的摘要说明
/// 
[DataObject]
public class Test
{
 [DataObjectMethod(DataObjectMethodType.Select, true)]
 public TestDatabase.TestDataTable GetTest()
 {
 return Singleton.Instance.GetTest();
 }
 [DataObjectMethod(DataObjectMethodType.Select, false)]
 public TestDatabase.TestDataTable GetTestById(int id)
 {
 return Singleton.Instance.GetTestById(id);
 }
 [DataObjectMethod(DataObjectMethodType.Insert, true)]
 public int?[] InsertTest(int? parentId, string name, DateTime? publishTime, decimal? price, bool? isGood, out int? minId)
 {
 // 仅为说明如何做错误处理
 if (String.IsNullOrEmpty(name))
 throw new ArgumentException("参数不能是空", "name");
 int? id = null;
 int? count = null;
 minId = null;
 Singleton.Instance.InsertTest(parentId, name, publishTime, price, isGood, ref id, ref count, ref minId);
 return new int?[] { id, count };
 }
 [DataObjectMethod(DataObjectMethodType.Delete, true)]
 public int? DeleteTest(int id)
 {
 int? rowAffected;
 rowAffected = Singleton.Instance.DeleteTest(id);
 return rowAffected;
 }
 [DataObjectMethod(DataObjectMethodType.Update, true)]
 public int? UpdateTest(int? id, int? parentId, string name, DateTime? publishTime, decimal? price, bool? isGood)
 {
 int? rowAffected;
 rowAffected = Singleton.Instance.UpdateTest(id, parentId, name, publishTime, price, isGood);
 return rowAffected;
 }
}
DataSourceControl/Test.aspx
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Test.aspx.cs"
 Inherits="DataSourceControl_Test" Title="数据源控件测试" %>
 
 
 
 
 
 
  DataKeyNames="Id" DataSourceID="ObjectDataSource1" Height="50px" Width="125px" OnItemInserted="DetailsView1_ItemInserted">
 
  SortExpression="Id" />
 
 
  InsertVisible="False" />
 
 
 
 
 
 
 
 
 
  SortExpression="Id" />
 
 
 
 
 
 
 
 
 
 
 
  DataSourceID="ObjectDataSource1" AllowPaging="True" AllowSorting="True" OnRowUpdating="GridView1_RowUpdating">
 
 
  SortExpression="Id" />
  NullDisplayText="我的值是NULL" />
 
  ReadOnly="true" />
 
 
 
 
 
  TypeName="Test" InsertMethod="InsertTest" DeleteMethod="DeleteTest" UpdateMethod="UpdateTest"
 OnInserting="ObjectDataSource1_Inserting" OnInserted="ObjectDataSource1_Inserted">
 
 <%--ConvertEmptyStringToNull属性默认为true--%>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  SelectMethod="GetTestById" TypeName="Test">
 
  Type="Int32" />
 
 
DataSourceControl/Test.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class DataSourceControl_Test : System.Web.UI.Page
{
 protected void Page_Load(object sender, EventArgs e)
 {
 }
 protected void ObjectDataSource1_Inserting(object sender, ObjectDataSourceMethodEventArgs e)
 {
 // 编程方式给参数赋值
 if (e.InputParameters["publishTime"] == null)
 {
 e.InputParameters["publishTime"] = DateTime.Now;
 }
 }
 protected void ObjectDataSource1_Inserted(object sender, ObjectDataSourceStatusEventArgs e)
 {
 // 错误处理
 if (e.Exception != null)
 {
 if (e.Exception.InnerException != null)
 {
 Exception inner = e.Exception.InnerException;
 if (inner is ArgumentException)
 {
 string paramName = ((ArgumentException)inner).ParamName;
 lblMsg.Text = string.Concat("参数 ", paramName, " 有问题");
 }
 }
 }
 else
 {
 int?[] ary = (int?[])e.ReturnValue;
 lblMsg.Text = "新插入信息的ID是:" + ary[0].ToString();
 lblMsg.Text += "
数据总数是:" + ary[1].ToString();
 lblMsg.Text += "
最小ID是:" + e.OutputParameters["minId"].ToString();
 }
 }
 protected void DetailsView1_ItemInserted(object sender, DetailsViewInsertedEventArgs e)
 {
 if (e.Exception != null)
 {
 // 错误已处理
 e.ExceptionHandled = true;
 // DetailsView保持插入状态
 e.KeepInInsertMode = true;
 }
 }
 protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
 {
 // 价格格式转换为decimal格式
 if (e.NewValues["Price"] != null)
 e.NewValues["Price"] = decimal.Parse(e.NewValues["Price"].ToString(), System.Globalization.NumberStyles.Currency);
 }
}
[源码下载]
作者:webabcd