C#DataTable DataSet DataRow区别详解

DataSet 是C#中用来存储数据库数据的。其实,它的作用是在内存中模拟数据库。我们现实生活中的数据库从大到小的基本结构类似于:数据库实例,表,列,行。在C#语言中,我们在内存中也模拟出了一个这样的关系型数据模型。对应关系如下表:

数据库  DataSet

表    DataTable

列    DataColumn

行    DataRow

 DataSet 和 物理数据库是两个客体,要使这两个客体保持一致,就需要使用 DataAdapter 类来同步两个客体。一般来说操作流程是:使用 DataAdapter 把物理数据库中的数据填充到 DataSet 中的 DataTable 里。当我们对内存中的 DataSet 做了增、删、改操作后,可以使用 DataAdapter 同步回数据库

datatable 中的DataRow 和dataColumn和表中的行、列操作一致,可以先确定Column.ColumnName,然后对row 赋值 

对DataTable中的元素赋值的方法可以使dt.rows[i][columnName]第i行列名对应下的表格数据;

dtContent = new DataTable();

 //人员ID列
        dtContent.Columns.Add("userID");
        //人员姓名列
        dtContent.Columns.Add("userName");

 DateTime dtStartDate, dtEndDate, cycleDate;
        if (DateTime.TryParse(startDate, out dtStartDate) && DateTime.TryParse(endDate, out dtEndDate))
        {
            cycleDate = dtStartDate;
            while (dtEndDate >= cycleDate)
            {
                dtContent.Columns.Add(cycleDate.ToString("yyyy-MM-dd"));//循环添加日期行
                cycleDate = cycleDate.AddDays(1);
            }
        }

 DataRow dr;
        for (int i = 0; i < objMyErpUser.Count(); i++)
        {
            if (objMyErpUser.Find(i))
            {
                dr = dtContent.NewRow();
                dr["userID"] = objMyErpUser.ID;//给id列赋值
                dr["userName"] = objMyErpUser.USERNAME;//给username列赋值
                for (int j = 2; j < dtContent.Columns.Count; j++)
                {
                    cellContent = "";

                    //查看值班表是否有记录
                    dtFindContent = objDutyList.FindByUserId(objMyErpUser.ID, dtContent.Columns[j].ColumnName);
                    for (int k = 0; k < dtFindContent.Rows.Count; k++)
                    {
                        if (cellContent != "")
                        {
                            cellContent += "<br/>";
                        }
                        cellContent += dtFindContent.Rows[k]["ITEM"] + " " + dtFindContent.Rows[k]["OT"] + "小时;";
                    }
                                        dr[j] = cellContent;
                }

                dtContent.Rows.Add(dr);//根据column.count大小从第二列开始给时间循环列赋值
            }
        }

DataSet

①属性

CaseSensitive:用于控制DataTable中的字符串比较是否区分大小写。

DataSetName:当前DataSet的名称。如果不指定,则该属性值设置为"NewDataSet"。如果将DataSet内容写入XML文件,DataSetName是XML文件的根节点名称。

DesignMode:如果在设计时使用组件中的DataSet,DesignMode返回True,否则返回False。

HasErrors:表示DataSet中的DataRow对象是否包含错误。如果将一批更改提交给数据库并将DataAdapter对象的ContinueUpdateOnError属性设置为True,则在提交更改后必须检查DataSet的HasErrors属性,以确定是否有更新失败。

NameSpacePrefix:指定XML命名空间和前缀

Relations:返回一个DataRelationCollection对象。

Tables:检查现有的DataTable对象。通过索引访问DataTable有更好的性能。

②方法

AcceptChangesRejectChanges:接受或放弃DataSet中所有挂起更改。调用AcceptChanges时,RowState属性值为Added或Modified的所有行的RowState属性都将被设置为UnChanged.任何标记为Deleted的DataRow对象将从DataSet中删除。调用RejectChanges时,任何标记为Added的DataRow对象将会被从DataSet中删除,其他修改过的DatRow对象将返回前一状态。

Clear:清除DataSet中所有DataRow对象。该方法比释放一个DataSet然后再创建一个相同结构的新DataSet要快。

CloneCopy:使用Copy方法会创建与原DataSet具有相同结构和相同行的新DataSet。使用Clone方法会创建具有相同结构的新DataSet,但不包含任何行。

GetChanges:返回与原DataSet对象具有相同结构的新DataSet,并且还包含原DataSet中所有挂起更改的行。

GetXmlGetXmlSchema:使用GetXml方法得到由DataSet的内容与她的架构信息转换为XML格式后的字符串。如果只希望返回架构信息,可以使用GetXmlSchema。

HasChange:表示DataSet中是否包含挂起更改的DataRow对象。

Merge:从另一个DataSet、DataTable或现有DataSet中的一组DataRow对象载入数据。

ReadXmlWriteXml:使用ReadXml方法从文件、TextReader、数据流或者XmlReader中将XML数据载入DataSet中。

Reset:将DataSet返回为未初始化状态。如果想放弃现有DataSet并且开始处理新的DataSet,使用Reset方法比创建一个DataSet的新实例好。

③事件

MergeFailed:在DataSet的Merge方法发生一个异常时触发。

2DataTable

①属性

②方法

③事件

ColumnChanged:在列的内容被改变之后触发

ColumnChangding:在列的内容被改变之前触发

RowChanged,RowChanging,RowDeleted,RowDeleting

3DataColumn

①属性

4DataRow

①属性

HasError:确定行是否包含错误。

Item:通过指定行的列数,列的名称或DataColumn对象本身,访问列的内容。

ItemArray:获取或设置行中所有列的值。

RowError:返回一个包含行错误信息的字符串。

RowState:返回DataRowState枚举中的值来表示行的当前状态。

Table:返回DataRow对象所在的DataTable。

②方法

AcceptChangesRejectChanges:提交和放弃挂起更改。

BeginEditCancelEditEndEdit

ClearErrors:清除DataRow中所有的错误。

Delete:Delete方法实际上并不从DataRow表的Row集合中删除该DataRow。当调用DataRow对象的Delete方法时,ADO.NET将该行标记为删除,之后调用SqlDataAdapter对象的Update方法来删除其在数据库中对应的行。

如果希望彻底删除DataRow,可以调用Delete方法,接着再调用它的AccepteChanges方法,还可以使用DataRowCollection对象的Remove方法完成相同的任务。

dataset ds =new datast();

datatable tel =new datatable();

ds..tables.add(tel);

string code=ds.tables["tel"].rows[0][0].tostring();

 

1、创建DataSet对象:

DataSet ds = new DataSet("DataSetName");

2、查看调用SqlDataAdapter.Fill创建的结构

da.Fill(ds,"Orders");

DataTable tbl = ds.Table[0];

foreach(DataColumn col in tbl.Columns)

Console.WriteLine(col.ColumnName);

3、查看SqlDataAdapter返回的数据

①DataRow对象

DataTable tbl = ds.Table[0];

DataRow row = tbl.Row[0];

Console.WriteLine(ros["OrderID"]);

检查存储在DataRow中的数据

DataTable tbl = row.Table;

foreach(DataColumn col in tbl.Columns)

Console.WriteLine(row[col]);

③检查DatTable中的DataRow对象

foreach(DataRow row in tbl.Rows)

DisplayRow(row);

4、校验DataSet中的数据

①校验DataColumn的属性:ReadOnly,AllowDBNull,MaxLength,Unique

②DataTable对象的Constrains集合:UiqueConstraints,Primarykey, ForeignkeyConstraints

通常不必刻意去创建ForeignkeyConstraints,因为当在DataSet的两个DataTable对象之间创建关系时会创建一个。

③用SqlDataAdapter.Fill模式来检索模式信息

5、编写代码创建DataTable对象

①创建DataTable对象:

DataTable tbl = new DataTable("TableName");

②将DataTable添加到DataSet对象的Table集合

DataSet ds = new DataSet();

DataTable tbl = new DataTable("Customers");

ds.Tables.Add(tbl);

DataSet ds = new DataSet();

DataTable tbl = ds.Tables.Add("Customers");

DataTable对象只能存在于至多一个DataSet对象中。如果希望将DataTable添加到多个DataSet中,就必须使用Copy方法或Clone方法。Copy方法创建一个与原DataTable结构相同并且包含相同行的新DataTable;Clone方法创建一个与原DataTable结构相同,但没有包含任何行的新DataTable。

③为DataTable添加列

DataTable tbl = ds.Tables.Add("Orders");

DataColumn col =tbl.Columns.Add("OrderID",typeof(int));

col.AllowDBNull = false;

col.MaxLength = 5;

col.Unique = true;

tbl.PrimaryKey = new DataColumn[]{tbl.Columns["CustomersID"]};

当设置主键时,AllowDBNull自动设置为False;

④处理自动增量列

DataSet ds = new DataSet();

DataTable tbl = ds.Tables.Add("Orders");

DataColumn col = tbl.Columns.Add("OrderID",typeof(int));

col.AutoIncrement = true;

col.AutoIncrementSeed = -1;

col.AutoIncrementStep = -1;

col.ReadOnly = true;

⑤添加基于表达式的列

tbl.Columns.Add("ItemTotal",typeof(Decimal),"Quantity*UnitPrice");

6、修改DataTable内容

①添加新DataRow

DataRow row = ds.Tables["Customers"].NewRow();

row["CustomerID"] = "ALFKI";

ds.Tables["Customers"].Rows.Add(row);

object[] aValues ={"ALFKI","Alfreds","Anders","030-22222"};

da.Tables["Customers"].LoadDataRow(aValues,false);

②修改当前行

修改行的内容逼供内不会自动修改数据库中相应的内容,对行所做的修改被视为是随后将使用SqlDataAdapter对象来提交交给数据库的待定的更改。

DataRow rowCustomer;

rowCustomer = ds.Tables["Custoemrs"].Rows.Find("ANTON");

if(rowCustomer == null)

    //没有查找客户

else

{

    rowCustomer["CompanyName"] ="NewCompanyName";

    rowCustomer["ContactName"] ="NewContactName";

}

 

//推荐使用这种方式

DataRow rowCustomer;

rowCustomer = ds.Tables["Custoemrs"].Rows.Find("ANTON");

if(rowCustomer == null)

    //没有查找客户

else

{

    rowCustomer.BeginEdit();

    rowCustomer["CompanyName"] ="NewCompanyName";

    rowCustomer["ContactName"] ="NewContactName";

    rowCustomer.EndEdit();

}

//null表示不修改该列的数据

obejct[] aCustomer ={null,"NewCompanyName","NewContactName",null}

DataRow rowCustomer;

rowCustomer = ds.Tables["Customers"].Rows.Find("ALFKI");

rowCustomer.ItemArray = aCustomer;

③处理DataRow的空值

//查看是否为空

DataRow rowCustomer;

rowCustomer = ds.Tables["Customers"].Rows.Find("ALFKI");

if(rowCustomer.IsNull("Phone"))

Console.WriteLine("It''''s Null");

else

Console.WriteLine("It''''s not Null");

 

//赋予空值

rowCustomer["Phone"] = DBNull.Value;

④删除DataRow

DataRow rowCustomer;

rowCustomer = ds.Tables["Customers"].Rows.Find("ALFKI");

rowCustomer.Delete();

⑤清除DataRow

DataRow rowCustomer = ds.Tables["Customers"].Rows.Find("ALFKI");

rowCustomer.ItemArray = aCustomer;

da.Tables["Customers"].Remove(rowCustomer);

或者

ds.Tables["Customers"].RemoveAt(intIndex);

⑥使用DataRow.RowState属性 :Unchanged,Detached,Added,Modified,Deleted

private void DemonstrateRowState()

{

    // Run a function to create a DataTable with one column.

    DataTable myTable = MakeTable();

    DataRow myRow;

    // Create a new DataRow.

    myRow = myTable.NewRow();

    // Detached row.

    Console.WriteLine("New Row " + myRow.RowState);

    myTable.Rows.Add(myRow);

    // New row.

    Console.WriteLine("AddRow " + myRow.RowState);

    myTable.AcceptChanges();

    // Unchanged row.

    Console.WriteLine("AcceptChanges " + myRow.RowState);

    myRow["FirstName"] = "Scott";

    // Modified row.

    Console.WriteLine("Modified " + myRow.RowState);

    myRow.Delete();

    // Deleted row.

    Console.WriteLine("Deleted " + myRow.RowState);

}

⑦检查DataRow中的挂起更改

DataRow rowCustomer;

rowCustomer = ds.Tables["Customers"].Rows.Find("ALFKI");

rowCustomer["CompanyName"] = "NewCompanyName";

string strNewCompanyName,strOldCompanyName;

Console.WriteLine(rowCustomer["CompanyName",DataRowVersion.Current]);

Console.WriteLine(rowCustomer["CompanyName",DataRowVersion.Original]);

⑧遍历DataSet

foreach(DataTable dt in dataSet.Tables)

foreach(DataRow dr in dt.Rows)

foreach(DataColumn dc in dr.Table.Columns)

Console.WriteLine(dr[dc]);

 

RowState 介绍

  1. 从不同位置载入 DataRow 后 RowState 的状态
  2. 修改, 更改, 删除后的 DataRow.RowState 转化
  3. 使用 AcceptChanges, RejectChanges, SetAdded, SetModified 方法后 DataRow.RowState 的转化
  4. 使用 ImportRow, Copy 方法后 DataRow.RowState 的转化
  5. 访问不同 RowState 的 DataRow 中的数据
  6. 获取 DataTable 中不同 RowState 的 DataRow

1. RowState 介绍

RowState 是 DataRow 很重要的一个属性, 表示 DataRow 当前的状态. RowState 有 Added, Modified, Unchanged, Deleted, Detached 几种, 分别表示 DataRow 被添加, 修改, 无变化, 删除, 从表中脱离. 在调用一些方法或者进行某些操作之后, 这些状态可以相互转化.

DataAdapter 可以根据 RowState 来决定如何影响数据库等存储位置. 如果 DataRow 的状态为 Added,DataAdapter 将把 DataRow 添加到数据库等存储位置, 对于 Modified, Deleted 则将执行更新和删除操作. 其实, 最终的操作效果还是决定于 DataAdapter 的 SelectCommand, UpdateCommand 等 DbCommand. 如果, 在 UpdateCommand 中写入 Delete 语句或者执行有删除操作的存储过程, 那么状态为 Modified 的 DataRow 最终将在数据库中删除而不是更新. (注: 下文中所说的 DataAdapter 操作均如此.)

2. 从不同位置载入 DataRow 后 RowState 的状态

a. 从 xml 文件或者使用 DataTable.Rows.Add(params object[]) 方法添加的 DataRow 的 RowState 为 Added.
使用上面方式增加的 DataRow, 如果使用 DataAdapter 更新, 将执行 insert 操作, 例如: 添加到 sql server 数据库中.

b. 如果 DataAdapter.AcceptChangesDuringFill 属性为 true, 使用 DataAdapter.Fill 方法填充的 DataRow的 RowState 为 Unchanged, 否则, 为 Added, 默认 AcceptChangesDuringFill 为 true.
例如: 默认情况下, 从 sql server 数据库读取的 DataRow, 然后直接使用 DataAdapter 更新的话, 是不会有任何数据被修改的, 因为 DataAdapter 不对状态为 Unchanged 的 DataRow 执行任何操作.

3. 修改, 更改, 删除后的 DataRow.RowState 转化

a. 对于状态为 Unchanged 或者 Modified 的 DataRow, 修改数据后的状态为 Modified.
这表示 DataRow 需要将自己的数据通过 DataAdapter 更新回数据库等存储位置. 因为, DataRow 中的数据可能已经和自己先前的版本不同.

b. 对于状态为 Added 的 DataRow, 修改数据后仍然为 Added.
DataAdapter 对状态为 Added 的 DataRow 将执行添加操作. 很明显, 即使修改 DataRow 仍然应该保持状态为 Added, 否则无法在 DataAdapter 更新的时候被添加到数据库等存储位置.

c. 如果 DataAdapter.AcceptChangesDuringUpdate 属性为 true, 使用 DataAdapter.Update 更新后的DataRow 的状态为 Unchanged, 否则, DataRow 的状态保持不变, 默认 AcceptChangesDuringUpdate 为 true.
默认情况下, 状态为 Unchanged 说明 DataRow 当前的数据没有经历过改变, 你可以认为和数据库中的数据一致, 但并非都如此.

d. 对于状态为 Unchanged 的 DataRow, 调用 Delete 方法后状态为 Deleted.
DataAdapter 对状态为 Deleted 的 DataRow 执行删除操作, 将数据库等存储位置的对应数据删除.

e. 对于状态为 Added 的 DataRow, 调用 Delete 方法后状态为 Detached.
Added 状态的 DataRow 可能并不存在于数据库等存储位置, 因此状态转化为 Detached 而不是 Deleted,DataAdapter 不会处理状态为 Detached 的 DataRow.

f. 使用 DataTable.Rows.Remove 方法移除 DataRow 后, DataRow 状态为 Detached.

4. 使用 AcceptChanges, RejectChanges, SetAdded, SetModified 方法后 DataRow.RowState 的转化

a. 状态为 Unchanged, Added, Modified 的 DataRow, 使用 DataRow.AcceptChanges 方法, 行状态将转化为 Unchanged.
以上三种状态的 DataRow, 其目的相当于添加或者修改数据, 因此接受变化后这些 DataRow 存在于 DataTable 中, 并且状态为 Unchanged. 如果这时使用 DataAdapter 更新, 将不会对数据库等存储位置有任何的影响, 因为状态已经为 Unchanged, 这本应该在 DataAdapter 更新后转化的.

b. 状态为 Deleted 的 DataRow, 使用 DataRow.AcceptChanges 方法, 行状态转化为 Detached.
目的为删除数据的 DataRow, 接受变化后就从 DataTable 中脱离, 因此状态变为 Detached.

c. 状态为 Detached 的 DataRow, 不能使用 DataRow.AcceptChanges 方法.

d. 状态为 Unchanged, Modified, Deleted 的 DataRow, 使用 DataRow.RejectChanges 方法, 行状态将转化为 Unchanged.
以上三种状态的 DataRow, 其目的相当于删除或者修改数据, 因此拒绝变化后这些 DataRow 存在于 DataTable 中, 并且状态为 Unchanged. 如果这时使用 DataAdapter 更新, 其情况将类似于 a.

e. 状态为 Added, Detached 的 DataRow, 使用 DataRow.RejectChanges 方法, 行状态将转化为 Detached.
状态为 Added 的 DataRow 目的在于添加, 因此拒绝后从 DataTable 脱离, 状态为 Detached.

f. 对状态为 Unchanged 的 DataRow, 可以使用 DataRow.SetAdded, DataRow.SetModified 方法使行状态转化为 Added 或者 Modified.
SetAdded, SetModified 方法对状态不是 Unchanged 的 DataRow 使用将抛出异常.

5. 使用 ImportRow, Copy 方法后 DataRow.RowState 的转化

a. 使用 DataTable.ImportRow 方法导入 DataRow 后, 导入的 DataRow 和原 DataRow 的行状态一致.
ImportRow 方法采用复制的方式导入 DataRow, 状态为 Detached 的 DataRow, 无法导入到 DataTable, 但不会产生异常.

b. 使用 DataTable.Copy 或者 DataSet.Copy 方法, DataRow 的状态保持不变.

6. 访问不同 RowState 的 DataRow 中的数据

a. 对于状态为 Added, Unchanged, Modified 的 DataRow, 可以方便的通过 DataRow[<列名>] 访问数据.

b. 状态为 Deleted 的 DataRow 需要使用 DataRow[<列名>, DataRowVersion.Original] 来访问.
对于已经调用 Delete 方法的 DataRow, 需要指定访问数据的 Original 版本.

c. 状态为 Detched 的 DataRow, 似乎没有方法访问其中的数据.
DataRow 已经从 DataTable 中移除, 这可能使其中的数据无法访问.

7. 获取 DataTable 中不同 RowState 的 DataRow

a. 可以通过 DataTable.GetChanges(DataRowState) 得到 DataTable 中不同 RowState 的 DataRow 的副本.
GetChanges 方法将返回一个新的 DataTable, 其中包含了指定行状态的 DataRow 的副本, 修改这些副本不会影响原 DataTable 中的 DataRow. 如果使用不带参数的 GetChanges 方法将返回包含行状态为 Added, Modified, Deleted 的 DataRow 副本的 DataTable. 可以使用位或运算符 | 组合获取多种状态的 DataRow. 另外, 状态为 Detached 的 DataRow 似乎是无法通过 GetChanges 方法获取的.

 

DataSet用法一:添加代码创建的表DataTable,设置主键外键,读取及修改Data...

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 dataset : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            DataSet ds = new DataSet();
            DataTable dt1 = new DataTable("user");
            DataTable dt2 = new DataTable("book");
           

            dt1.Columns.Add("uid", typeof(Int32));
            dt1.Columns.Add("uname", typeof(string));

            dt2.Columns.Add("bid", typeof(Int32));
            dt2.Columns.Add("bname", typeof(string));
           
            ds.Tables.Add(dt1);
            ds.Tables.Add(dt2);
           
            object[] userdata = new object[2];
            object[] bookdata = new object[2];

            userdata[0] = 1;
            userdata[1] = "wjwu";
          
            bookdata[0] = 1;
            bookdata[1] = "English";

            Session["ds"]=ds;

            dt1.Rows.Add(userdata);
            dt2.Rows.Add(bookdata);

            fill();
        }
        
    }
    private void fill()
    {
        DataSet ds = new DataSet();
        ds = (DataSet)Session["ds"];
        GridView1.DataSource = ds.Tables["user"];
        GridView1.DataBind();

        GridView2.DataSource = ds.Tables["book"];
        GridView2.DataBind();
    }

  
    protected void addrow_Click(object sender, EventArgs e)
    {
       //增加表数据
        DataSet ds = new DataSet();
        ds = (DataSet)Session["ds"];

        object[] add = new object[2];
        add[0] = 2;
        add[1] = "lucy";

        try
        {
            ds.Tables["user"].Rows.Add(add);
            Session["ds"] = ds;
            fill();
        }
        catch (Exception ex)
        {
            Response.Write("<script>alert('" + ex.Message + "')</script>");
        }       
    }
   
    protected void pk_Click(object sender, EventArgs e)
    {
        //设置主键
        DataSet ds = new DataSet();
        ds = (DataSet)Session["ds"];

        UniqueConstraint uc = new UniqueConstraint("userpk", ds.Tables["user"].Columns["uid"],true);
        ds.Tables["user"].Constraints.Add(uc);
       
        Session["ds"] = ds;
        fill();
    }

    protected void fk_Click(object sender, EventArgs e)
    {//设置外键
       
        DataSet ds = new DataSet();
        ds = (DataSet)Session["ds"];
        ForeignKeyConstraint fkc = new ForeignKeyConstraint("userfk", ds.Tables["user"].Columns["uid"], ds.Tables["book"].Columns["bid"]);
        ds.Tables["book"].Constraints.Add(fkc);
        Session["ds"] = ds;
        fill();
    }


    protected void Button1_Click(object sender, EventArgs e)
    {
        DataSet ds = new DataSet();
        ds = (DataSet)Session["ds"];

        Label1.Text = ds.Tables["user"].Rows[0]["uname"].ToString();
    }


    protected void Button2_Click(object sender, EventArgs e)
    {
        DataSet ds = new DataSet();
        ds = (DataSet)Session["ds"];
        ds.Tables["book"].Rows[0]["bname"] = TextBox1.Text;
        Session["ds"] = ds;
        fill();
    }
}

posted @ 2014-04-02 15:17  码农小小强  阅读(2163)  评论(0编辑  收藏  举报