使用C#操作Oracle Spatial的SDO_GEOMETRY对像(读取和写入)

首先,这个需要使用ODAC,也就是Oracle.DataAccess.dll,新出的托管Oracle.ManagedDataAccess.dll不支持Object Type,无法使用

 
先根据SDO_GEOMETRY对象的内容,在C#中构建一个对应的类,然后在读取和写入时使用OracleParameter来操作这个类的对象,达到读取和写入数据库SDO_GEOMETRY对象的目的
 
类名为SdoGeometry,主要代码如下(其中还用到了自定义的SdoPoint,OracleArrayTypeFactory和OracleCustomTypeBase类,其代码见附件的相应文件)
[csharp] view plain copy
 
 使用C#操作Oracle Spatial的SDO_GEOMETRY对像(读取和写入)使用C#操作Oracle Spatial的SDO_GEOMETRY对像(读取和写入)
  1. [OracleCustomTypeMappingAttribute("MDSYS.SDO_GEOMETRY")]  
  2.   public class SdoGeometry : OracleCustomTypeBase<SdoGeometry>  
  3.   {  
  4.     private enum OracleObjectColumns { SDO_GTYPE, SDO_SRID, SDO_POINT, SDO_ELEM_INFO, SDO_ORDINATES }  
  5.     private decimal? sdo_Gtype;  
  6.     [OracleObjectMappingAttribute(0)]  
  7.     public decimal? Sdo_Gtype  
  8.     {  
  9.       get { return sdo_Gtype; }  
  10.       set { sdo_Gtype = value; }  
  11.     }  
  12.     private decimal? sdo_Srid;  
  13.     [OracleObjectMappingAttribute(1)]  
  14.     public decimal? Sdo_Srid  
  15.     {  
  16.       get { return sdo_Srid; }  
  17.       set { sdo_Srid = value; }  
  18.     }  
  19.     private SdoPoint point;  
  20.     [OracleObjectMappingAttribute(2)]  
  21.     public SdoPoint Point  
  22.     {  
  23.       get { return point; }  
  24.       set { point = value; }  
  25.     }  
  26.     private decimal[] elemArray;  
  27.     [OracleObjectMappingAttribute(3)]  
  28.     public decimal[] ElemArray  
  29.     {  
  30.       get { return elemArray; }  
  31.       set { elemArray = value; }  
  32.     }  
  33.     private decimal[] ordinatesArray;  
  34.     [OracleObjectMappingAttribute(4)]  
  35.     public decimal[] OrdinatesArray  
  36.     {  
  37.       get { return ordinatesArray; }  
  38.       set { ordinatesArray = value; }  
  39.     }  
  40.     [OracleCustomTypeMappingAttribute("MDSYS.SDO_ELEM_INFO_ARRAY")]  
  41.     public class ElemArrayFactory : OracleArrayTypeFactoryBase<decimal> {}  
  42.     [OracleCustomTypeMappingAttribute("MDSYS.SDO_ORDINATE_ARRAY")]  
  43.     public class OrdinatesArrayFactory : OracleArrayTypeFactoryBase<decimal> {}  
  44.     public override void MapFromCustomObject()  
  45.     {  
  46.       SetValue((int)OracleObjectColumns.SDO_GTYPE, Sdo_Gtype);  
  47.       SetValue((int)OracleObjectColumns.SDO_SRID, Sdo_Srid);  
  48.       SetValue((int)OracleObjectColumns.SDO_POINT, Point);  
  49.       SetValue((int)OracleObjectColumns.SDO_ELEM_INFO, ElemArray);  
  50.       SetValue((int)OracleObjectColumns.SDO_ORDINATES, OrdinatesArray);  
  51.     }  
  52.     public override void MapToCustomObject()  
  53.     {  
  54.       Sdo_Gtype = GetValue<decimal?>((int)OracleObjectColumns.SDO_GTYPE);  
  55.       Sdo_Srid = GetValue<decimal?>((int)OracleObjectColumns.SDO_SRID);  
  56.       Point = GetValue<SdoPoint>((int)OracleObjectColumns.SDO_POINT);  
  57.       ElemArray = GetValue<decimal[]>((int)OracleObjectColumns.SDO_ELEM_INFO);  
  58.       OrdinatesArray = GetValue<decimal[]>((int)OracleObjectColumns.SDO_ORDINATES);  
  59.     }  
  60.   }  


 
从数据库里读取的代码为(示例表只有两列,id列为number类型,geo列为SDO_GEOMTRY类型):
[csharp] view plain copy
 
 使用C#操作Oracle Spatial的SDO_GEOMETRY对像(读取和写入)使用C#操作Oracle Spatial的SDO_GEOMETRY对像(读取和写入)
  1. OracleCommand cmd = new OracleCommand()  
  2. cmd.Connection = con;   
  3.  cmd.CommandType = CommandType.Text;  
  4. cmd.CommandText = " select id,geo from geoinfo ";  
  5.  using (OracleDataReader readerGeoInfo = cmd.ExecuteReader())  
  6.  {  
  7.    while (readerGeoInfo.Read())  
  8.    {  
  9.      GeoInfo geoInfo = new GeoInfo();  
  10.      if (!readerGeoInfo.IsDBNull(0))  
  11.      {  
  12.        geoInfo.Id = readerGeoInfo.GetDecimal(0);  
  13.      }  
  14.      if (!readerGeoInfo.IsDBNull(1))  
  15.      {  
  16.        geoInfo.Geo = (SdoGeometry)readerGeoInfo.GetValue(1);   
  17.      }  
  18.      geoInfoList.Add(geoInfo);  
  19.    }  
  20.    readerGeoInfo.Close();  
  21.  }  


 
插入的代码为:
[csharp] view plain copy
 
 使用C#操作Oracle Spatial的SDO_GEOMETRY对像(读取和写入)使用C#操作Oracle Spatial的SDO_GEOMETRY对像(读取和写入)
  1. cmd.CommandText = " insert into geoinfo values (geoinfo_seq.nextval,:param) ";  
  2.           cmd.Parameters.Clear();  
  3.           OracleParameter oracleParameterGeo = new OracleParameter();  
  4.           oracleParameterGeo.OracleDbType = OracleDbType.Object;  
  5.           oracleParameterGeo.UdtTypeName = "MDSYS.SDO_GEOMETRY";  
  6.           cmd.Parameters.Add(oracleParameterGeo);  
  7.           //creating point  
  8.           SdoGeometry geoPoint = new SdoGeometry();  
  9.           geoPoint.Sdo_Gtype = 2001;   
  10.           geoPoint.Point = new SdoPoint();  
  11.           geoPoint.Point.X = 200;  
  12.           geoPoint.Point.Y = 400;  
  13.           oracleParameterGeo.Value = geoPoint;  
  14.           //insert point in table geoinfo  
  15.           cmd.ExecuteNonQuery();  
  16.           //creating polygon  
  17.           SdoGeometry geoPolygon = new SdoGeometry();  
  18.           geoPolygon.Sdo_Gtype = 2003;  
  19.           geoPolygon.ElemArray = new decimal[] { 1, 1003, 1 };  
  20.           geoPolygon.OrdinatesArray = new decimal[] { 3, 3, 3, 10, 10, 10, 10, 3, 3, 3 };  
  21.           oracleParameterGeo.Value = geoPolygon;   
  22.           //insert polygon into table geoinfo   
  23.           cmd.ExecuteNonQuery();  


 
在实际使用中,使用DataAdapter的Fill方法将Select  *的查询结果放到DataTable中时,如果已经定义了SdoGeometry的类,查询结果会自动地将DataTable的那列认为是SdoGeometry,非常方便 ,例如 
 
 OracleDataAdapter mAdp = new OracleDataAdapter("select * from geoinfo", con);
 DataTable mDst = new DataTable();
 mAdp.Fill(mDst);
 
此时mDst的第二列数据类型即为SdoGeometry