博客园  :: 首页  :: 联系 :: 管理

ObjectDataSource 传递自定义对象参数

Posted on 2010-01-07 12:46  sunrack  阅读(1396)  评论(0)    收藏  举报

SQLDataSource虽然使用起来比较简单,但它与数据库之间的直接访问,导致我们在使用的过程中缺乏了灵活性。
在开发过程中我们为了实现程序的合理结构和良好的代码重用功能,一般会把程序用三层来进行架构。而SQLDataSource这种直接连接数据库的功能,对三层架构来说很难实现。
如果不用SQLDataSource控件,那GridView的好多功能就不能完全正常发挥其威力。为了解决这个问题,微软为我们提供了ObjectDataSource这个控件。

ObjectDataSource控件并不直接与数据库之间进行连接,可以通过对业务对象的调用,实现对数据库的操作。

一、ObjectDataSource控件的几个重要属性
    SelectMethod:ObjectDataSource控件执行查询时调用的方法名。
   DeleteMethod:ObjectDataSource控件执行删除时调用的方法名。
    UpdateMethod:ObjectDataSource控件执行更新时调用的方法名。
    InsertMethod:ObjectDataSource控件执行插入时调用的方法名。

二、ObjectDataSource控件的几个重要方法
    Select():调用SelectMethod进行查询
    Insert():调用InsertMethod进行插入
    Update():调用UpdateMethod进行更新
   Delete():调用DeleteMethod进行删除

三、ObjectDataSource控件的几个重要的子元素
    InsertParameters:为InsertMethod的方法提供参数
    UpdateParameters:为UpdateMethod的方法提供参数
    DeleteParameters:为DeleteMethod的方法提供参数
    SelectParameters:为SelectMethod的方法提供参数
四、举例
    1.配置连接字符串
    2.编写业务模块(此处我用数据库的insert/update/delete/select来替代,在实际应用中,业务模块远比此复杂)
        在此业务功能模块用的是SQLDataSource对象读取数据的,当然也可以用ADO.NET来读取数据
        public class FruitDA
        {
            private SqlDataSource sd;
            public FruitDA()
            {
                sd = new SqlDataSource();
                sd.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["conn1"].ToString();;
            }
            public DataView select()
            {
                sd.SelectCommand = "select * from fruit";
                sd.DataSourceMode = SqlDataSourceMode.DataSet;
                DataView ds = (DataView)sd.Select(DataSourceSelectArguments.Empty);
                return ds;
            }
            public void update(string ids,string name,decimal price,string source,string stack)
            {
                sd.UpdateCommand = "update fruit set name = @name,price = @price,source = @source,stack = @stack where ids = @ids";
                sd.UpdateParameters.Add("ids", TypeCode.String, ids);
                sd.UpdateParameters.Add("name",TypeCode.String,name);
                sd.UpdateParameters.Add("price", TypeCode.Decimal, price.ToString());
                sd.UpdateParameters.Add("source",TypeCode.String,source);
                sd.UpdateParameters.Add("stack",TypeCode.String,stack);
                sd.Update();
            }
            public void insert(string ids, string name, decimal price, string source, string stack)
            {
                sd.InsertCommand = "insert into fruit (ids,name,price,source,stack) values(@ids,@name,@price,@source,@stack)";
                sd.InsertParameters.Add("ids", TypeCode.String, ids);
                sd.InsertParameters.Add("name", TypeCode.String, name);
                sd.InsertParameters.Add("price", TypeCode.Decimal, price.ToString());
                sd.InsertParameters.Add("source", TypeCode.String, source);
                sd.InsertParameters.Add("stack", TypeCode.String, stack);
                sd.Insert();
            }
            public void delete(string ids)
            {
                sd.DeleteCommand = "delete from fruit where ids = @ids";
                sd.DeleteParameters.Add("ids",TypeCode.String,ids);
                sd.Delete();
            }
        }
    3.配置ObjectDataSource和GridView,实现update/select/delete功能
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ids" DataSourceID="s">
            <Columns>
                <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
                <asp:BoundField DataField="ids" />
                <asp:BoundField DataField="name" />
                <asp:BoundField DataField="price" />
                <asp:BoundField DataField="source" />
                <asp:BoundField DataField="stack" />
            </Columns>
        </asp:GridView>
        <asp:ObjectDataSource ID="s" runat="server" SelectMethod="select" TypeName="FruitDA" DeleteMethod="delete" UpdateMethod="update" InsertMethod="insert" >
            <DeleteParameters>
                <asp:Parameter Name="ids" Type="String" />
            </DeleteParameters>
            <UpdateParameters>
                <asp:Parameter Name="ids" Type="String" />
                <asp:Parameter Name="name" Type="String" />
                <asp:Parameter Name="price" Type="Decimal" />
                <asp:Parameter Name="source" Type="String" />
                <asp:Parameter Name="stack" Type="String" />
            </UpdateParameters>
            <InsertParameters>
                <asp:ControlParameter Name="ids" ControlID = "txtIds" Type="String" />
                <asp:ControlParameter Name="name" ControlID = "txtName" Type="String" />
                <asp:ControlParameter Name="price" ControlID = "txtPrice" Type="Decimal" />
                <asp:ControlParameter Name="source" ControlID = "txtSource" Type="String" />
                <asp:ControlParameter Name="stack" ControlID = "txtStack" Type="String" />
            </InsertParameters>
        </asp:ObjectDataSource>
        <asp:TextBox ID="txtIds" runat="server"></asp:TextBox>
        <asp:TextBox ID="txtName" runat="server"></asp:TextBox>
        <asp:TextBox ID="txtPrice" runat="server"></asp:TextBox>
        <asp:TextBox ID="txtSource" runat="server"></asp:TextBox>
        <asp:TextBox ID="txtStack" runat="server"></asp:TextBox><br />
        <asp:Button ID="Button1" runat="server" Text="Insert" OnClick="Button1_Click" />
    4.实现插入功能的代码
         protected void Button1_Click(object sender, EventArgs e)
        {
            s.Insert();
        }           
(车延禄)

自定义Parameter
    在SqlDataSource和ObjectDataSource控件中有七种类型的参数,但这七种类型的参数有时还不能满足我的需求。
问题提出:
    在ObjectDataSource中,是通过SelectMethod、InsertMethod、UpdateMethod和DeleteMethod四个属性来调用业务逻辑对象的方法,业务逻辑对象的方法需要的参数可以通过ObjectDataSource控件相应的Parameter属性传入。这些Parameter的参数来源与参数类型是固定的,在遇到以下两种情况是无法解决的。
     a、参数不是直接来源于控件、Session、Cookie、QueryString等,而是把某个对象中的属性值作为参数传后业务逻辑的方法,如何进行参数赋值。
     b、业务逻辑方法的形参不是常用的string、int、float等类型,而是一个自定义的类型,如何进行参数赋值。
自定义Parameter:
    要自定义Parameter需要编写一个类派生自Parameter类,并且重写其Evaluate方法。
        public class CustomParameter:Parameter
        {
            object obj; //传递给业务逻辑对象的形参的值
            public object Value
            {
                get{ return obj;}
                set{ obj = value;}
            }
            public CustomParameter(){}
            //传递参数名和参数值,调用父类构造方法给参数名赋值,并把参数值保存到obj里。
            public CustomParameter(string name, object value) : base(name)
            {
                obj = value;
            }
            public CustomParameter(string name, TypeCode type, object value) : base(name, type)
            {
                obj = value;
            }
            public CustomParameter(CustomParameter original) : base(original)
            {
                obj = original.Value;
            }
            //被DataSource控件绑定时自动调用,更新并返回 Parameter 对象的值。
            protected override object Evaluate(HttpContext context, Control control)
            {
                return Value;
            }
        }
    数据访问逻辑:
        public class FruitDB
        {
            private SqlConnection conn;
            public FruitDB()
            {
                conn = new Conn().Connection;
            }
            public List<FruitData> select()
            {
                List<FruitData> fruitlist = new List<FruitData>();
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = "select * from fruit";
                conn.Open();
                SqlDataReader dr = cmd.ExecuteReader();
                while (dr.Read())
                {
                    FruitData data = new FruitData(dr["ids"].ToString(),dr["name"].ToString(),decimal.Parse(dr["price"].ToString()),dr["source"].ToString(),dr["stack"].ToString(),dr["image"].ToString());
                    fruitlist.Add(data);
                }
                conn.Close();
                return fruitlist;
            }
            public void insert(FruitData fd)
            {
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = "insert into fruit values(@ids,@name,@price,@source,@stack,@image)";
                cmd.Parameters.AddWithValue("@ids",fd.Ids);
                cmd.Parameters.AddWithValue("@name",fd.Name);
                cmd.Parameters.AddWithValue("@price", fd.Price);
                cmd.Parameters.AddWithValue("@source",fd.Source);
                cmd.Parameters.AddWithValue("@stack",fd.Stack);
                cmd.Parameters.AddWithValue("@image",fd.Image);
                conn.Open();
                cmd.ExecuteNonQuery();
                conn.Close();
            }
        }
    FruitData实体类:
        public class FruitData
        {
            private string ids,name,price,source,stack,image;
            public string Ids
            {
                get{ return ids;}
                set{ ids = value;}
            }
            public string Name
            {
                get{ return name;}
                set{ name = value;}
            }
            public decimal Price
            {
                get{ return price;}
                set{ price = value;}
            }
            public string Source
            {
                get{ return source;}
                set{ source = value;}
            }
            public string Stack
            {
                get{ return stack;}
                set{ stack = value;}
            }
            public string Image
            {
                get{ return image;}
                set{ image = value;}
            }
            public FruitData(string ids, string name, decimal price, string source, string stack, string image)
            {
                this.ids = ids;
                this.name = name;
                this.price = price;
                this.source = source;
                this.stack = stack;
                this.image = image;
            }
        }(车延禄)
      界面代码:
            <asp:GridView ID="GridView1" runat="server" DataSourceID="ObjectDataSource1">
            </asp:GridView>
            <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" InsertMethod="insertdb"
                SelectMethod="select" TypeName="FruitDB">
            </asp:ObjectDataSource>
            <asp:TextBox ID="txtIds" runat="server"></asp:TextBox>
            <asp:TextBox ID="txtName" runat="server"></asp:TextBox>
            <asp:TextBox ID="txtPrice" runat="server"></asp:TextBox>
            <asp:TextBox ID="txtSource" runat="server"></asp:TextBox>
            <asp:TextBox ID="txtStack" runat="server"></asp:TextBox>
            <asp:TextBox ID="txtImage" runat="server"></asp:TextBox><br />
            <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
这里需要注意的是:在insert的时候不要加入 DataObjectTypeName="FruitData",否则会报“没有可以插入的值。请检查“values”” 的错误,而在更新删除的时候,必须要加入DataObjectTypeName="FruitData"这句声明。
        后置代码类:
            //构造一个FruitData对象
            FruitData fd = new FruitData(txtIds.Text, txtName.Text, decimal.Parse(txtPrice.Text), txtSource.Text, txtStack.Text, txtImage.Text);
            ObjectDataSource1.InsertParameters.Clear();
            //创建自定义的的Parameter,并创建的FruitData对象传入
            CustomParameter cp = new CustomParameter("fd", fd);
            //添加自定义的参数
            ObjectDataSource1.InsertParameters.Add(cp);
            //执行查询
            ObjectDataSource1.Insert();  

 

 

 

正如我们在上一节的教程中所看到的,有很多可供选择的方式把参数的值传递到OjbectDataSource的方法里。假如参数值是采用硬编码方式,来源于页面上的一个Web控件,又或者其他可被数据源Parameter对象读取的源,那么这个值可以绑定到输入参数而不需要写一行的代码。

然而有些时候,参数值来自某些在数据源的内置Parameter对象里还没有计算出来的源。假如我们的站点支持我们的考虑那么我们也许希望参数基于当前登录用户。又或者我们在参数传送到ObjectDataSource的隐含对象的方法前做一些客户化定制。

无论什么时候调用ObjectDataSource的Seelect方法,它都会首先触发它的Selecting事件,然后才调用ObjectDataSource的隐含对象的方法,完成后则激发ObjectDataSource ObjectDataSource的Selected 事件(图一说明这些事件的顺序)。可以在Selecting事件的事件委托中对参数的值进行设置或更改。


图 1: ObjectDataSource的Selected 和 Selecting 事件分别在调用它的隐含对象的方法之前和之后触发