第九章-使用C#和ADONET操作数据库.ppt

上传人:hyn****60 文档编号:70707309 上传时间:2023-01-25 格式:PPT 页数:46 大小:362.50KB
返回 下载 相关 举报
第九章-使用C#和ADONET操作数据库.ppt_第1页
第1页 / 共46页
第九章-使用C#和ADONET操作数据库.ppt_第2页
第2页 / 共46页
点击查看更多>>
资源描述

《第九章-使用C#和ADONET操作数据库.ppt》由会员分享,可在线阅读,更多相关《第九章-使用C#和ADONET操作数据库.ppt(46页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、数据库原理及应用1 页第第9 9章章:使用使用C#C#和和ADO.NETADO.NET操作数据库操作数据库 本章要点数据提供程序的选择vSqlConnection的使用vOleDbConnection的使用vOdbcConnection的使用vOracleConnection的使用数据的获取vCommand的使用vDataReader的使用vDataSet和DataAdapter的使用1/23/2023数据库原理及应用2 页nConnectionString类似于OLEDB连接字符串,但并不相同。可以使用ConnectionString属性连接到数据库(P198)。Persist Securi

2、ty Info=False;Integrated Security=SSPI;database=northwind;server=mySQLServern下面的例子创建一个SqlConnection对象并设置它的一些属性。public void CreateSqlConnection()SqlConnection myConnection=new SqlConnection();myConnection.ConnectionString=Persist Security Info=False;”+“Integrated Security=SSPI;database=northwind;”+“s

3、erver=mySQLServer;Connect Timeout=30;myConnection.Open();SqlConnectionSqlConnection的使用的使用1/23/2023数据库原理及应用3 页n例子:执行一条插入语句l创建一个OleDbConnection和一个OleDbCommand对象。lOleDbConnection被设置为OleDbCommand的Connection,并被打开。l调用ExecuteNonQuery并关闭该连接。为了完成此任务,将向ExecuteNonQuery传递一个连接字符串和一个查询字符串(一个SQLINSERT语句)。OleDbConn

4、ectionOleDbConnection的使用的使用1/23/2023数据库原理及应用4 页public void InsertRow(string myConnectionString)/If the connection string is null,use a default.if(myConnectionString=)myConnectionString=Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=Northwind;+Integrated Security=SSPI;OleDbConnection myConne

5、ction=new OleDbConnection(myConnectionString);string myInsertQuery=INSERT INTO Customers (CustomerID,CompanyName)Values(NWIND,Northwind Traders);OleDbCommand myCommand=new OleDbCommand(myInsertQuery);myCommand.Connection=myConnection;myConnection.Open();myCommand.ExecuteNonQuery();myCommand.Connecti

6、on.Close();OleDbConnectionOleDbConnection的使用(的使用(Cont.Cont.)1/23/2023数据库原理及应用5 页OdbcConnectionOdbcConnection的使用的使用n例子:执行一条插入语句l创建一个OdbcConnection和一个OdbcCommand对象。lOdbcConnection被设置为OdbcCommand的Connection,并被打开。l调用ExecuteNonQuery并关闭该连接。为了完成此任务,将向ExecuteNonQuery传递一个连接字符串和一个查询字符串(一个SQLINSERT语句)。1/23/202

7、3数据库原理及应用6 页public void InsertRow(string myConnection)/If the connection string is null,use a default.if(myConnectionString=)myConnection=DRIVER=SQL Server;SERVER=MyServer;Trusted_connection=yes;DATABASE=northwind;OdbcConnection myConn=new OdbcConnection(myConnectionString);string myInsertQuery=INSE

8、RT INTO Customers (CustomerID,CompanyName)Values(NWIND,Northwind Traders);OdbcCommand myOdbcCommand=new OdbcCommand(myInsertQuery);myOdbcCommand.Connection=myConn;myConn.Open();myOdbcCommand.ExecuteNonQuery();myOdbcCommand.Connection.Close();OdbcConnectionOdbcConnection的使用的使用(Cont.)(Cont.)1/23/2023数

9、据库原理及应用7 页OracleConnectionOracleConnection的使用的使用nMicrosoft.NET Framework Data Provider for Oracle(以下简称为.NET for Oracle)是一个.NET Framework的组件。n 这个组件为使用.NET访问Oracle数据库提供了支持。n 使用.NET和Oracle的开发人员,不必继续使用那个并不十分“专业”的OLE DB来访问Oracle数据库。n 该组件的设计非常类似.NET中内置的Microsoft.NET Framework Data Provider for SQL Server和

10、OLE DB。1/23/2023数据库原理及应用8 页nCommand对象是对数据存储执行命令的对象。n实际上,当从Connection对象中运行一条命令时,已经隐含地创建一个Command对象。但是Connection对象在处理命令的功能上受到一定的限制,而Command对象是特别为处理命令的各方面问题而创建的:l有时其他对象允许向命令传入参数,但在Connection对象中不能指定参数的任何细节。使用Command对象允许指定参数(以及输出参数和命令执行后的返回值)的精确细节(比如,数据类型和长度)。l因此,除了执行命令和得到一系列返回记录,也可能得到一些由命令提供的附加信息。l对于那些不

11、返回任何记录的命令,如插入新数据或更新数据的SQL查询,Command对象也是有用的。数据的获取:创建数据的获取:创建CommandCommand对象对象1/23/2023数据库原理及应用9 页n建立了数据源的连接和设置了命令之后,Command对象执行SQL命令有三种方法:lExecuteNonQuery、ExecuteReader和ExecuteScalar:ExecuteNonQuery执行命令,但不返回任何结果ExecuteReader执行命令,返回一个DataReaderExecuteScalar执行命令,返回一个值lSqlCommand类也提供了下面两个方法:ExecuteResu

12、ltset为将来使用而保留ExecuteXmlReader执行命令,返回一个XmlReader。n用ExecuteNonQuery执行命令不会返回结果集,只会返回语句影响的记录行数。l它适合执行插入、更新、删除之类不返回结果集的命令l如果是SELECT语句,那么返回的结果是-1数据的获取:执行命令数据的获取:执行命令1/23/2023数据库原理及应用10 页下面的程序对 Orders 表执行了更新并做了查询。using System;using System.Data;using System.Data.SqlClient;public class myDataAccess public st

13、atic void Main()SqlConnection conn=new SqlConnection(Server=localhost;Database=Northwind;User ID=sa;PWD=sa);SqlCommand cmd=new SqlCommand(update Orders set OrderDate=2004-9-1 where OrderID=10248,conn);try conn.Open();int i=cmd.ExecuteNonQuery();Console.WriteLine(i.ToString()+rows affected by UPDATE)

14、;cmd.CommandText=select*from Orders;i=cmd.ExecuteNonQuery();Console.WriteLine(i.ToString()+rows affected by SELECT);1/23/2023数据库原理及应用11 页catch(Exception ex)Console.WriteLine(ex.Message);finally conn.Close();n使用ExecuteReader方法执行的命令,可以返回一个DataReader的实例或者IDataReader接口的结果集。通过DataReader对象就能够获得数据的行集合(关于Da

15、taReader的使用将在后面说明)n例子:using System;using System.Data;using System.Data.SqlClient;数据的获取:执行命令(数据的获取:执行命令(Cont.Cont.)1/23/2023数据库原理及应用12 页public class myDataAccess public static void Main()SqlConnection conn=new SqlConnection(Server=localhost;Database=Northwind;Uer ID=sa;PWD=sa);SqlCommand cmd=new SqlC

16、ommand(select top 20*from Orders,conn);SqlDataReader reader;/或者或者IDataReader reader;try conn.Open();reader=cmd.ExecuteReader();while(reader.Read()Console.WriteLine(reader0.ToString();reader.Close();catch(Exception ex)Console.WriteLine(ex.Message);finally conn.Close();数据的获取:执行命令(数据的获取:执行命令(Cont.Cont.

17、)1/23/2023数据库原理及应用13 页图7-3执行结果图编译执行结果如图7-3:1/23/2023数据库原理及应用14 页nExecuteReader方法,如果想获得数据的记录行数,可以通过selectcount(*)这样的语句取得一个聚合的行集合。n对于这样求单个值的语句,Command对象还有更有效率的方法ExecuteScalar。l它能够返回对应于第一行第一列的对象(System.Object),通常使用它来求聚合查询结果。l 注意:如果要把返回结果转化成精确的类型,数据库在查询中就必须强制将返回的结果转换,否则引发异常。n例子:using System;using System

18、.Data;using System.Data.SqlClient;数据的获取:执行命令(数据的获取:执行命令(Cont.Cont.)1/23/2023数据库原理及应用15 页public class myDataAccess public static void Main()SqlConnection conn=new SqlConnection(Server=localhost;Database=Northwind;Uer ID=sa;PWD=sa);SqlCommand cmd=new SqlCommand(select count(*)from Orders,conn);try con

19、n.Open();int i=(int)cmd.ExecuteScalar();Console.WriteLine(record num:+i.ToString();cmd.CommandText=select cast(avg(Freight)as int)from Orders;int avg=(int)cmd.ExecuteScalar();Console.WriteLine(avg:+avg.ToString();cmd.CommandText=select avg(Freight)from Orders;avg=(int)cmd.ExecuteScalar();/引发异常引发异常 C

20、onsole.WriteLine(avg:+avg.ToString();catchfinallyconn.Close();1/23/2023数据库原理及应用16 页n编译执行结果如图7-4下:图7-4执行结果图n这个程序中,最后一个查询将引发异常,因为聚合返回的结果是float类型的,无法转换。n其他命令:lExecuteResultSet(只用于Sql提供者)。这个方法标记为“为将来使用而保留”,如果不小心调用了它,就会抛出一个异常System.NotSupportedException。lExecuteXmlReader(只用于Sql提供者)。顾名思义,这个方法执行命令,给调用者返回一个

21、XmlReader对象。1/23/2023数据库原理及应用17 页n参数化的查询能够对性能有一定的优化,因为带参数的SQL语句只需要被SQL执行引擎分析过一次。nCommand的Parameters能够为参数化查询设置参数值。Parameters是一个实现IDataParamterCollection接口的参数集合。n不同的数据提供程序的Command对参数传递的使用不太一样,其中SqlClient和OracleClient只支持SQL语句中命名参数而不支持问号占位符,必须使用命名参数,而OleDb和Odbc数据提供程序只支持问号占位符,不支持命名参数。数据的获取:参数化查询数据的获取:参数化

22、查询1/23/2023数据库原理及应用18 页n对于查询语句SqlClient必须使用命名参数,类似于下面的写法:SELECT*FROM Customers WHERE CustomerID=CustomerIDOracle的命名参数前面不用,使用(:),写为(:CustomerID)。n对于OleDb或者Odbc必须使用?占位符,类似于下面的写法:SELECT*FROM Customers WHERE CustomerID=?数据的获取:参数化查询数据的获取:参数化查询1/23/2023数据库原理及应用19 页下面以SqlServer为例,说明其使用方法:using System;using

23、 System.Data;using System.Data.SqlClient;public class myDataAccess public static void Main(String args)SqlConnection conn=new SqlConnection(Server=localhost;Database=Northwind;UID=sa;PWD=sa);SqlCommand cmd=new SqlCommand(select*from Orders where OrderID=oid,conn);SqlDataReader reader;try int param=C

24、onvert.ToInt32(args0);cmd.Parameters.Add(oid,param);/使用命名参数使用命名参数 cmd.Parameters0.Direction=ParameterDirection.Input;conn.Open();reader=cmd.ExecuteReader();1/23/2023数据库原理及应用20 页while(reader.Read()Console.WriteLine(reader0.ToString();reader.Close();catch(Exception ex)Console.WriteLine(ex.Message);fin

25、ally conn.Close();对于OleDb或者Odbc数据提供程序的命令参数,只需要把参数按照占位符从左到右的顺序,匹配给Parameters集合就行了。1/23/2023数据库原理及应用21 页using System;using System.Data;using System.Data.OleDb;public class myDataAccess public static void Main(String args)OleDbConnection conn=new OleDbConnection(Provider=SQLOLEDB;Server=locahost;Databa

26、se=Northwind;User ID=sa;PWD=sa);OleDbCommand cmd=new OleDbCommand(select*from Orders where OrdeID=?or EmployeeID=?,conn);OleDbDataReader reader;try int param1=Convert.ToInt32(args0);int param2=Convert.ToInt32(args1);/参数对象还需要名字,但是和查询语句中的参数无关参数对象还需要名字,但是和查询语句中的参数无关 cmd.Parameters.Add(aaa,param1);cmd.P

27、arameters.Add(bbb,param2);cmd.Parameters0.Direction=ParameterDirection.Input;cmd.Parameters1.Direction=ParameterDirection.Input;n例子:1/23/2023数据库原理及应用22 页conn.Open();reader=cmd.ExecuteReader();while(reader.Read()Console.WriteLine(reader0.ToString();reader.Close();catch(Exception ex)Console.WriteLine(

28、ex.Message);finally conn.Close();1/23/2023数据库原理及应用23 页n使用Command对象访问数据库的存储过程,需要指定CommandType属性,这是一个CommandType枚举类型,默认情况下CommandType表示CommandText命令为SQL批处理,CommandType.StoredProcedure值指定执行的命令是存储过程。n类似于参数化查询,存储过程的参数也可以使用Parameters集合来设置,其中Parameter对象的Direction属性用于指示参数是只可输入、只可输出、双向还是存储过程返回值参数。数据的获取:执行存储过

29、程数据的获取:执行存储过程1/23/2023数据库原理及应用24 页n需要注意的是如果使用ExecuteReader返回存储过程的结果集,那么除非DataReader关闭,否则无法使用输出参数。n和参数化一样,OleDb或者Odbc数据提供程序不支持存储过程的命名参数,需要按照参数从左到右顺序,匹配Parameters集合。n例子参见教材P211数据的获取:执行存储过程数据的获取:执行存储过程1/23/2023数据库原理及应用25 页n DataReader(数据阅读器)是从一个数据源中选择某些数据的最简单方法,但这也是功能最弱的一个方法。nDataReader不如DataSet强大,但是在很

30、多情况下我们需要的是灵活的读取数据而不是大量的在内存里面缓存数据。l如果在网络上每个用户都缓存大量的DataSet,这很可能导致服务器内存不足。l另外DataReader尤其适合读取大量的数据,因为它不在内存中缓存数据。数据的获取:数据的获取:DataReaderDataReader的使用的使用1/23/2023数据库原理及应用26 页nDataReader对象提供对数据库访问快速的、未缓冲的、只前向移动的只读游标,对数据源进行逐行访问数据;即,它通过一次读入一个行的方式遍历所有的行。n使用DataReader的时候,不能直接实例化DataReader类;而是通过执行Command对象的Exe

31、cuteReader方法返回它的实例。例如:OleDbDataReader OleDbReader=OleDbComm.ExecuteReader();使用OleDbCommand对象的ExecuteReader方法实例化了一个DataReader。DataReaderDataReader的使用(的使用(Cont.Cont.)1/23/2023数据库原理及应用27 页n例子:using System;using System.Data.OleDb;using System.Data;namespace OlDbRead /Class1 的摘要说明。的摘要说明。/class Class1 /应用

32、程序的主入口点。应用程序的主入口点。/STAThreadDataReaderDataReader的使用(的使用(Cont.Cont.)1/23/2023数据库原理及应用28 页static void Main(string args)string source=Provider=SQLOLEDB;+server=localhost;“+uid=sa;pwd=;“+database=northwind;string select=SELECT ContactName,CompanyName FROM Customers;OleDbConnection conn=new OleDbConnecti

33、on(source);conn.Open();OleDbCommand cmd=new OleDbCommand(select,conn);OleDbDataReader aReader=cmd.ExecuteReader();while(aReader.Read()Console.WriteLine(0 from 1,aReader.GetString(0),aReader.GetString(1);aReader.Close();conn.Close();1/23/2023数据库原理及应用29 页n使用命令行为指定DataReader的特征 SqlDataRader dr cmd.Exec

34、uteReader(CommandBehavior.CloseConnection);上面使用的是CommandBehavior.CloseConnection,作用是关闭DataReader的时候自动关闭对应的ConnectionObject。这样可以避免忘记关闭DataReader对象以后关闭Connection对象。这个参数能保证开发者记得关闭连接。n遍历DataReader中的记录下面是使用DataReader常用的格式:while(dr.Reader()/do something with the current record 注意如果你对每一条记录的操作可能花费比较长的时间,那么意

35、味着阅读器将长时间打开,那么数据库连接也将维持长时间的打开状态。此时使用非连接的DataSet或许更好一些。DataReaderDataReader读取数据读取数据1/23/2023数据库原理及应用30 页n访问字段的值DataReader有两种方法访问字段的值。第一种是Item属性,此属性返回字段索引或者字段名字对应的字段的值。第二种是Get方法,此方法返回由字段索引指定的字段的值。nItem属性每个DataReader类都定义一个Item属性。假如现有一个DataReader实例dr,对应的sql语句是selectFid,Fnamefromfriend,则可以使用下面的方法取得返回的值:o

36、bject ID=dr“Fid”;object Name=dr“Fname”;或者:object ID=dr0;object Name=dr0;注意:索引总是从0开始的。另外本例使用的是object来定义对ID和Name,因为Item属性返回的值是object型,但是可以强制类型转换:int ID=(int)dr“Fid”;string Name=(string)dr“Fname”;DataReaderDataReader读取数据(读取数据(Cont.Cont.)1/23/2023数据库原理及应用31 页nGet方法每个DataReader都定义了一组Get方法,下面的例子使用该方式访问Fid

37、和Fname的值:int ID=dr.GetInt32(0);string Name=dr.GetString(1);注意:虽然这些方法把数据从数据源类型转化为.NET数据类型,但是不执行其他的数据转换,如不会把16位整数转换为32位的。所以必须使用正确的Get方法。另外Get方法不能使用字段名来访问字段,下面的访问方法是错误的:int ID=dr.GetInt32(“Fid”);/错误错误 string Name=dr.GetString(“Fname”);/错误错误DataReaderDataReader读取数据(读取数据(Cont.Cont.)1/23/2023数据库原理及应用32 页n

38、DataReader提供了另一个遍历结果集的方法NextResult(),其作用是把数据读取器移动到下一个结果集,这个方法可以与Read()方法协同工作。例如,下面的代码使用DataReader实现了操作两个结果集:using System;using System.Data;using System.Data.SqlClient;namespace ConsoleApplication1 class Class1 /应用程序的主入口点。应用程序的主入口点。/STAThread static void Main(string args)DataReaderDataReader中使用多个结果集中

39、使用多个结果集1/23/2023数据库原理及应用33 页/TODO:在此处添加代码以启动应用程序在此处添加代码以启动应用程序string connstr=server=.;Integrated Security=SSPI;database=Northwind;SqlConnection conn=new SqlConnection(connstr);string SQL=select companyname,contactname from customers;+select firstname,lastname from employees;SqlCommand sqlComm=new Sq

40、lCommand(SQL,conn);try conn.Open();SqlDataReader dr=sqlComm.ExecuteReader();do Console.WriteLine(0tt1,dr.GetName(0),dr.GetName(1);while(dr.Read()Console.WriteLine(0tt1,dr.GetSqlString(0),dr.GetSqlString(1);while(dr.NextResult();1/23/2023数据库原理及应用34 页 dr.Close();catch(Exception e)Console.WriteLine(e.M

41、essage);finally conn.Close();1/23/2023数据库原理及应用35 页nDataSet对象与ADORecordSet对象相似,但功能更为强大,并具有另一重要区别:DataSet始终是断开的。nDataSet对象表示数据的缓存,具有类似数据库的结构,如表、列、关系和约束。n尽管DataSet可以像数据库那样运行,但DataSet对象不直接与数据或其他源数据进行交互。l这使得开发人员能够使用始终保持一致的编程模型,而不用理会源数据的驻留位置。l所有来自于数据库、XML文件、代码或用户输入的数据都可添加到DataSet对象中。这样,对DataSet进行的更改可以在更新源

42、数据之前进行跟踪和验证。lDataSet对象的GetChanges方法实际上是创建了另一个DataSet,该DataSet只包含对数据做出的更改。然后,DataAdapter(或其他对象)使用此DataSet来更新原始的数据源。DataSetDataSet简介简介1/23/2023数据库原理及应用36 页n创建一个空DataSet对象:DataSet ds=new DataSet();这样创建的DataSet对象的DataSetName属性被设置为NewDataSet。该属性描述DataSet的内部名称,以便以后引用。n也可以在构造函数中指定,它以字符串的形式接受名称:DataSet ds=n

43、ew DataSet(“MyDataSet”);或者可以这样简单地设置属性:DataSet ds=new DataSet();ds.DataSetName=“MyDataSet”;DataSetDataSet简介(简介(Cont.Cont.)1/23/2023数据库原理及应用37 页nDataAdapter是连接到数据库以填充DataSet的对象。然后,它又连接回数据库,根据DataSet保留数据时所执行的操作来更新数据库中的该数据。n下面介绍使用DataAdapter填充DataSet的方法。l 首先定义SQL查询,创建数据库连接,然后创建和初始化数据适配器:SqlDataAdapter d

44、a=new SqlDataAdapter(SQL,sqlConn);l 接着创建DataSet对象:DataSet ds=new DataSet();l 此时,得到的只是空DataSet。关键代码行是使用数据适配器的Fill()方法执行查询,检索数据,填充DataSet:da.Fill(ds,”Products”);Fill()方法从内部使用DataReader访问数据库数据和表达式,然后使用它填充DataSet。这里Products是DataSet中要填充数据的表名(如果未显式给出,自动命名为Tablen n从空开始)。DataAdapterDataAdapter简介简介1/23/2023数

45、据库原理及应用38 页n下面的代码显示了使用SqlDataAdapter的另一种方法,为此,将其SelectCommand属性设置为SqlCommand对象。我们可以使用SelectCommand得到或设置SQL语句或存储过程:SqlDataAdapter da=new SqlDataAdapter();Da.SelectCommand=new SqlCommand(SQL,sqlConn);DataSet ds=new DataSet();da.Fill(ds,”Products”);n 以DataTable 对象的形式提取DataSet中每个表数据,并使用该对象访问表中实际数据。如前面Da

46、taSet含有一个表:DataTable dt=ds.Tables”Products”;n 最后,使用嵌套的foreach循环,从每个行访问列数据,并且把输出输出到屏幕:foreach(DataRow dRow in dt.Rows)foreach(DataColumn dCol in dt.Columns)Console.WriteLine(dRowdCol);DataAdapterDataAdapter简介(简介(Cont.Cont.)1/23/2023数据库原理及应用39 页n数据集是一个容器,因此需要用数据填充它。填充数据集时,将引发各种事件,应用约束检查等等。可以用多种方法填充数据集

47、:l 调用数据适配器的 Fill 方法。这导致适配器执行 SQL 语句或存储过程,然后将结果填充到数据集中的表中。如果数据集包含多个表,每个表可能有单独的数据适配器,因此必须分别调用每个适配器的 Fill 方法。l 通过创建 DataRow 对象并将它们添加到表的 Rows 集合,手动填充数据集中的表(只能在运行时执行此操作,无法在设计时设置 Rows 集合)。l 将 XML 文档或流读入数据集。l 合并(复制)另一个数据集的内容。如果应用程序从不同的来源(例如,不同的 XML Web Services)获取数据集,但是需要将它们合并为一个数据集,该方法会很有用。n使用DataSet和Data

48、Adapter访问数据库例子:利用利用DataSetDataSet和和DataAdapterDataAdapter访问数据访问数据1/23/2023数据库原理及应用40 页using System;using System.Data;using System.Data.SqlClient;using System.Drawing;using System.Windows.Forms;public class DataGridSample:Form DataSet ds;DataGrid myGrid;static void Main()Application.Run(new DataGridS

49、ample();public DataGridSample()InitializeComponent();void InitializeComponent()this.ClientSize=new System.Drawing.Size(550,450);myGrid=new DataGrid();myGrid.Location=new Point(10,10);myGrid.Size=new Size(500,400);myGrid.CaptionText=Microsoft.NET DataGrid;this.Text=C#Grid Example;this.Controls.Add(my

50、Grid);ConnectToData();myGrid.SetDataBinding(ds,Suppliers);1/23/2023数据库原理及应用41 页 void ConnectToData()/Create the ConnectionString and create a SqlConnection /Change the data source value to the name of your computer string cString=Persist Security Info=False;Integrated Security=SSPI;database=northwin

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 生活常识

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁