[转]在.Net中使用Oracle的表类型和对象类型
本文转自:http://www.cnblogs.com/studyzy/archive/2010/10/13/1850161.html
在一般的数据存取操作过程中,如果要对一个主表和对应的子表进行插入操作,那么我们最常见的写法就是写两个存储过程或者SQL语句,一个负责主表数据插入,一个负责子表数据插入,然后在一个事务中实现主表和子表数据的插入。 现在遇到一个问题是,能否在一个存储过程中实现主表和子表数据的插入呢?那么就需要将一对多的数据作为存储过程的参数传入。这种情况下就需要使用表类型。下面以一个学生和班级的例子来说明: 先建立一个班级表和一个学生表,一个班级里面有多个学生。 代码 CREATE TABLE CLASS
(
CLASSID NUMBER () PRIMARY KEY,
CLASSNAME VARCHAR2 ( BYTE) NOT NULL
); CREATE TABLE STUDENT
(
STUID NUMBER() PRIMARY KEY,
CLASSID NUMBER() NOT NULL,
STUNAME NVARCHAR2() NOT NULL,
STUGENDER CHAR( BYTE),
STUBIRTHDAY DATE,
DESCRIPTION NVARCHAR2()
); CREATE SEQUENCE CLASSID; CREATE SEQUENCE STUDENTID; 首先我们需要在Oracle中创建一个学生的对象类型,这个对象类型中就是学生的属性: CREATE OR REPLACE type StudentType as object
(
StuName nvarchar2(),
StuGender char(),
StuBirthday date,
StuDescription nvarchar2()
); 接下来是将这个学生类型创建成表类型: CREATE OR REPLACE type StuList as table of StudentType; 接下来就是写我们的一个插入存储过程,将班级和学生列表作为参数传入,具体脚本为: 代码 CREATE OR REPLACE PROCEDURE ZY.AddClassStudent( ClassName in varchar2,
Students in StuList
) IS BEGIN
insert into Class values(classid.nextval,ClassName);
insert into Student(StuID,ClassID,StuName,Stugender,Stubirthday,Description)
select studentid.nextval,classid.currval,StuName,StuGender,StuBirthday,studescription
from TABLE(Students);
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
RAISE;
END AddClassStudent; 现在Oracle服务器上的各个对象已经创建完成,接下来就是要编写C#代码,连接到Oracle数据库,插入数据了。 在C#项目中添加Oracle.DataAccess的引用,这是Oracle为.Net开发的类库,可以从官网下载。添加引用后,再添加命名空间: using Oracle.DataAccess.Types;
using Oracle.DataAccess.Client; 然后再创建Student对应的类: 代码 public class Student : IOracleCustomType
{
#region IOracleCustomType Members public void FromCustomObject(Oracle.DataAccess.Client.OracleConnection con, IntPtr pUdt)
{
if (StudentName != null)
OracleUdt.SetValue(con, pUdt, "STUNAME", StudentName);
else
throw new NullReferenceException("STUNAME is null");
OracleUdt.SetValue(con, pUdt, "STUGENDER", Gender);
OracleUdt.SetValue(con, pUdt, "STUBIRTHDAY", Birthday);
OracleUdt.SetValue(con, pUdt, "STUDESCRIPTION", Description);
} public void ToCustomObject(Oracle.DataAccess.Client.OracleConnection con, IntPtr pUdt)
{
StudentName = (String)OracleUdt.GetValue(con, pUdt, "STUNAME");
Gender = (String)OracleUdt.GetValue(con, pUdt, "STUGENDER");
Birthday = (DateTime)OracleUdt.GetValue(con, pUdt, "STUBIRTHDAY");
Description = (String)OracleUdt.GetValue(con, pUdt, "STUDESCRIPTION");
} #endregion [OracleObjectMappingAttribute("STUNAME")]
public String StudentName { get; set; } [OracleObjectMapping("STUGENDER")]
public string Gender { get; set; } [OracleObjectMapping("STUBIRTHDAY")]
public DateTime Birthday { get; set; } [OracleObjectMapping("STUDESCRIPTION")]
public string Description { get; set; } } 并添加Student类对应Oracle对象类型的映射,通过Attribute来指定: 代码 [OracleCustomTypeMappingAttribute("STUDENTTYPE")]
public class StudentFactory : IOracleCustomTypeFactory
{
#region IOracleCustomTypeFactory Members public IOracleCustomType CreateObject()
{
return new Student();
} #endregion
} 现在StudentType类型已经创建完成,接下来就是创建StuList类型对应的类: 代码 [OracleCustomTypeMappingAttribute("STULIST")]
public class StudentList_TabFactory : IOracleArrayTypeFactory
{
#region IOracleArrayTypeFactory Members public Array CreateArray(int numElems)
{
return new Student[numElems];
} public Array CreateStatusArray(int numElems)
{
return null;
} #endregion
} 这里可以看到,返回的是Student的数组。现在准备工作都已经完成,接下来就是初始化一点数据,然后调用存储过程了,代码如下: 代码 Student s1 = new Student() { StudentName = "张三", Birthday = Convert.ToDateTime("1984/12/29"), Gender = "M", Description = "HAHA。" };
Student s2 = new Student() { StudentName = "李四", Birthday = Convert.ToDateTime("1982/12/29"), Gender = "F", Description = "A。" };
Student s3 = new Student() { StudentName = "王五", Birthday = Convert.ToDateTime("1982/1/29"), Gender = "M", Description = "B。" };
Student s4 = new Student() { StudentName = "小月月", Birthday = Convert.ToDateTime("1985/10/11"), Gender = "F", Description = "C。" };
List<Student> ss1 = new List<Student>();
ss1.Add(s1);
ss1.Add(s2);
ss1.Add(s3);
ss1.Add(s4); string conn = "Data Source=BRDWDEV;User Id=zy;Password=123;";
using (OracleConnection oc = new OracleConnection(conn))
{
oc.Open(); OracleCommand cmd = oc.CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure; cmd.CommandText = "ZY.ADDCLASSSTUDENT"; OracleParameter p0 = new OracleParameter();
p0.OracleDbType = OracleDbType.Varchar2;
p0.UdtTypeName = "CLASSNAME";
p0.Value = "测试班级名";
p0.Direction = ParameterDirection.Input;
cmd.Parameters.Add(p0); OracleParameter p1 = new OracleParameter();
p1.OracleDbType = OracleDbType.Array;
p1.Direction = ParameterDirection.Input;
p1.UdtTypeName = "STULIST";//注意这里是类型,而不是参数名
p1.Value = ss1.ToArray();//注意这里应该是数组
cmd.Parameters.Add(p1); int count = cmd.ExecuteNonQuery();
Console.WriteLine(count);
oc.Close();
} 以此类推,其实还可以把班级建立对象类型,然后再建立班级列表类型,这样就可在一个存储过程中插入多个班级,每个班级多个学生的数据。 【出自博客园深蓝居,转载请注明作者出处】
[转]在.Net中使用Oracle的表类型和对象类型的更多相关文章
- hibernate课程 初探单表映射3-3 对象类型
本节简介: 1 简介对象类型(重点是音视频blob类型) 2 demo(对图片的写入数据库与读取) 1 简介对象类型 映射类型 java类型 标准sql类型 mysql类型 oracle类型 bina ...
- sql*loader以及oracle外部表加载Date类型列
Oracle sqlldr LOAD DATAINFILE *INTO TABLE testFIELDS TERMINATED BY X'9'TRAILING NULLCOLS( c2 &quo ...
- Oracle创建表、修改字段类型
1.创建表 1.创建表 create table SCM_PER( --SCM_PER表名 ID ) primary key,--主键ID USERID ),--用户ID --Permission v ...
- oracle修改表列名和列类型
--修改列名alter table 表名 rename column 旧列名 to 新列名;--修改列类型alter table 表名 modify (列名varchar(255));
- Oracle锁表与解锁 对象锁与解锁
阅读目录 锁表与解锁 查看锁表进程SQL语句 解锁 对象锁与解锁 回到顶部 锁表与解锁 查看锁表进程SQL语句 select * from v$session t1, v$locked_object ...
- hibernate_05_单表操作_对象类型
本篇使用hibernate输出一个对象(图片) 先写一个java类 package com.imooc.hibernate; import java.sql.Blob; import java.uti ...
- 如何利用Oracle外部表导入文本文件的数据
同事最近在忙数据一致性比对工作,需要对不同文本文件中的数据进行比对,有的文件较大,记录较多,如果用普通的文本编辑器打开的话,很显然,会很卡,甚至打不开. 基于此,可将该文本文件的数据导入到数据库中,在 ...
- Oracle 错误表
ORA-00001: 违反唯一约束条件 (.) ORA-00017: 请求会话以设置跟踪事件 ORA-00018: 超出最大会话数 ORA-00019: 超出最大会话许可数 ORA-00020: 超出 ...
- oracle对象类型
Oracle的对象类型 对象类型 在PL/SQL中,面向对象的程序设计师基于对象类型来完成的.对象类型是用户自定义的一种复合数据类型,它封装了数据结构和用于操纵这些数据结构的过程和函数. 数据库的对象 ...
随机推荐
- C++ ODR规则与dlopen 问题
问题: 开发平台*.so插件的时候遇到相同的函数名称出现在不同的.so文件中,假设分别为a.so和b.so,b.so要使用a.so中的定义函数 a(),而在dlopen会先加载a.so然后加载b.so ...
- opencv 在工业中的应用:二维标定
在工业中经常要检测一个零件的尺寸,但是图像处理得到的是像素值,怎么才能得到实际的毫米值呢?这就要用到二维标定,我用OPENCV写了一个利用标定板进行标定的DEMO. 很多商业软件都没有二维标定的功能, ...
- 《Oracle Database 12c DBA指南》第一章 - 基本技能简介
当前关于12c的中文资料比较少,本人将关于DBA的一部分官方文档翻译为中文,很多地方为了帮助中国网友看懂文章,没有按照原文句式翻译,翻译不足之处难免,望多多指正. 1 基本技能简介 作为一个数据库管理 ...
- CodeForce---Educational Codeforces Round 3 USB Flash Drives (水题)解题报告
对于这题明显是用贪心算法来解决问题: 下面贴出笔者的代码: #include<cstdio> #include<iostream> #include<algorithm& ...
- NOIP2009 靶形数独
4.靶形数独 (sudoku.pas/c/cpp) [问题描述] 小城和小华都是热爱数学的好学生, 近,他们不约而同地迷上了数独游戏,好胜的他们想用数独来一比高低.但普通的数独对他们来说都过于简单了, ...
- 五个小例子教你搞懂 JavaScript 作用域问题
众所周知,JavaScript 的作用域和其他传统语言(类C)差别比较大,掌握并熟练运用JavaScript 的作用域知识,不仅有利于我们阅读理解别人的代码,也有助于我们编写自己的可靠代码. 下面笔者 ...
- codeforce 606A - Magic Spheres
题意:a,b,c三种球,能把俩个一样的球变成另一颜色不一样的球.给你目标x,y,z,问能否经过变化至少达打目标. #include<iostream> #include<stdio. ...
- 关于JavaScripting API您不知道的5件事
现在,许多 Java 开发人员都喜欢在 Java 平台中使用脚本语言,但是使用编译到 Java 字节码中的动态语言有时是不可行的.在某些情况中,直接编写一个 Java 应用程序的脚本 部分 或者在一个 ...
- tomcat登陆WEB显示无权限问题&& tomcat无限循环启动问题
tomcat登陆WEB显示无权限问题 The user specified as a definer (”@’%') does not exist 原因分析 因为创建视图使用的是xff@%用户(目前已 ...
- A Tour of Go Switch evaluation order
Switch cases evaluate cases from top to bottom, stopping when a case succeeds. (For example, switch ...