基于ArcGIS10.0和Oracle10g的空间数据管理平台十(C#开发)-空间数据导入RDBMS上-MDB格式
2013-04-05 18:53
1221 查看
前面第九篇把Shape格式导入已经完成了,在这个以后我又陆续加入其他几篇这个项目相关知识介绍的博文,加入那些知识的目的是为了让博友们能够更加清楚这个项目的一切相关知识,以便更好的理解这个项目。现在开始完成MDB格式导入Oracle数据库。
和Shape相同的部分就不在讲解了,只讲解与Shape不同的实现部分!
1.添加一个MDB格式的空间数据文件到导入列表,并显示其相关信息。
[csharp] view
plaincopy
/// <summary>
/// 添加一个MDB格式的文件到导入控件列表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void addFileBtn_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
//打开MDB文件
string StrFilter = "MDB文件(.mdb) | *.mdb";
ofd.Filter = StrFilter;
string ImportMDBName;
if (ofd.ShowDialog() == DialogResult.OK)
{
ImportMDBName = ofd.FileName;
}
else
{
return;
}
//得到文件名和目录名
string ImportFileName = System.IO.Path.GetFileName(ImportMDBName);
string ImportFilePath = System.IO.Path.GetDirectoryName(ImportMDBName);
//检查文件是否已经存在DataGridView中,没有就加载到其中
if (!fileIsExist(ImportFileName))
{
object[] obj = new object[2];
obj[0] = ImportFileName;
obj[1] = ImportFilePath;
dataGridViewX1.Rows.Add(obj);
addTableNameToDataGridView(ImportMDBName);
}
}
这个函数又调用了一个专门用于检测文件是否已经被导入了的函数,实现如下:
[csharp] view
plaincopy
/// <summary>
/// 判断文件名是否已经存在在DataGridView中了
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
private bool fileIsExist(string filename)
{
bool result = false;
for (int i = 0; i < dataGridViewX1.Rows.Count; ++i)
{
if (filename == dataGridViewX1.Rows[i].Cells[0].Value.ToString())
{
result = true;
break;
}
}
return result;
}
2.读出一个MDB格式文件里所有的表相关信息并加载到控件中显示。
[csharp] view
plaincopy
/// <summary>
/// 读出一个MDB格式文件里所有的表相关信息并加载到控件中显示
/// </summary>
/// <param name="filename"></param>
private void addTableNameToDataGridView(string filename)
{
//打开mdb文件所在的工作空间
IWorkspaceFactory wf = new AccessWorkspaceFactory();
IFeatureWorkspace pAccessFW = wf.OpenFromFile(filename, 0) as IFeatureWorkspace;
IWorkspace pAccessW = pAccessFW as IWorkspace;
object[] obj = new object[5];
SqlHelper sh = new SqlHelper();
string sql = string.Empty;
//1.遍历mdb的每一个要素集,并加载表信息到DataGridViewX2中
IEnumDataset enumDataset = pAccessW.get_Datasets(esriDatasetType.esriDTFeatureDataset);
IFeatureDataset featureDs = enumDataset.Next() as IFeatureDataset;
while (featureDs != null)
{
IFeatureClass pFeatureClass;
IFeatureClassContainer fcContainer = featureDs as IFeatureClassContainer;
for (int i = 0; i < fcContainer.ClassCount; i++)
{
pFeatureClass = fcContainer.get_Class(i);
obj[0] = true;
obj[1] = pFeatureClass.AliasName;
obj[2] = pFeatureClass.AliasName;
sql = "select table_name from layer l,element e where table_name='"
+ pFeatureClass.AliasName.ToLower()
+ "' and e.id=l.pid and e.category='矢量数据'";
if (sh.GetRecordCount(sql) > 0)
{
obj[3] = "是";
}
else
{
obj[3] = "否";
}
//检查此表结构是否符合标准
if (CheckFields(pFeatureClass.Fields, pFeatureClass.AliasName))
{
obj[4] = true;
}
else
{
obj[4] = false;
}
dataGridViewX2.Rows.Add(obj);
}
featureDs = enumDataset.Next() as IFeatureDataset;
}
//2.遍历mdb的每一个独立要素类,,并加载表信息到DataGridViewX2中
enumDataset = pAccessW.get_Datasets(esriDatasetType.esriDTFeatureClass);
IDataset dataset = enumDataset.Next();
while (dataset != null)
{
IFeatureClass pFeatureClass = dataset as IFeatureClass;
obj[0] = true;
obj[1] = pFeatureClass.AliasName;
obj[2] = pFeatureClass.AliasName;
sql = "select table_name from layer l,element e where table_name='"
+ pFeatureClass.AliasName.ToLower()
+ "' and e.id=l.pid and e.category='矢量数据'";
if (sh.GetRecordCount(sql) > 0)
{
obj[3] = "是";
}
else
{
obj[3] = "否";
}
//检查此表结构是否符合标准
if (CheckFields(pFeatureClass.Fields, pFeatureClass.AliasName))
{
obj[4] = true;
}
else
{
obj[4] = false;
}
dataGridViewX2.Rows.Add(obj);
dataset = enumDataset.Next();
}
//3.遍历mdb的每一个属性表,,并加载表信息到DataGridViewX2中
enumDataset = pAccessW.get_Datasets(esriDatasetType.esriDTTable);
dataset = enumDataset.Next();
while (dataset != null)
{
ITable t = dataset as ITable;
obj[0] = true;
obj[1] = dataset.Name;
obj[2] = dataset.Name;
sql = "select table_name from layer l,element e where table_name='"
+ dataset.Name.ToLower()
+ "' and e.id=l.pid and e.category='矢量数据'";
if (sh.GetRecordCount(sql) > 0)
{
obj[3] = "是";
}
else
{
obj[3] = "否";
}
//检查此表结构是否符合标准
if (CheckFields(t.Fields, dataset.Name))
{
obj[4] = true;
}
else
{
obj[4] = false;
}
dataGridViewX2.Rows.Add(obj);
dataset = enumDataset.Next();
}
//判断所有的是否通过了检查,可以是人为的,也可能是自动检查,通过则使能完成按钮
//否则禁止完成按钮
bool isAll = true;
for (int i = 0; i < dataGridViewX2.Rows.Count; ++i )
{
if (!bool.Parse(dataGridViewX2.Rows[i].Cells[4].Value.ToString()))
{
isAll = false;
break;
}
}
if (isAll)
{
finishBtn.Enabled = true;
}
else
{
finishBtn.Enabled = false;
}
}
由上面的代码可以看出要读取出MDB文件中所有的表结构信息需要分三种情况,一、所有在数据集里面的表;二、独立(游离)的表;三、属性表。每读取一个表结构的信息就检测这个表的字段是否符合数据库中定义好的数据结构,完成这个功能是调用函数CheckFields,这个函数定义和实现如下所示:
[csharp] view
plaincopy
/// <summary>
/// 检查字段是否符合数据标准定义
/// </summary>
/// <param name="pSourceFileds">字段集</param>
/// <param name="strTableName">对应的标准名</param>
/// <returns></returns>
private bool CheckFields(IFields pSourceFileds, string strTableName)
{
SqlHelper sh = new SqlHelper();
string sql = "select * from fielddefine where table_name ='"
+ strTableName.ToUpper() + "' or table_name='" + strTableName.ToLower() + "'";
if (pSourceFileds.FieldCount != sh.GetRecordCount(sql))
{
return false;
}
bool result = true;
OracleDataReader odr = sh.ReturnDataReader(sql);
object[] obj1 = new object[4];
object[] obj2 = new object[4];
for (int i = 0; i < pSourceFileds.FieldCount; i++)
{
odr.Read();
if (pSourceFileds.FindField(odr["NAME"].ToString()) >= 0)
{
IField pSourceField = pSourceFileds.get_Field(pSourceFileds.FindField(odr["NAME"].ToString()));
obj1[0] = pSourceField.Name;
obj1[1] = pSourceField.Type;
obj1[2] = pSourceField.Length;
obj1[3] = pSourceField.IsNullable;
obj2[0] = odr["NAME"].ToString();
if (odr["TYPE"].ToString() == "RowID")
{
obj2[1] = esriFieldType.esriFieldTypeOID;
}
else if (odr["type"].ToString() == "整数型")
{
obj2[1] = esriFieldType.esriFieldTypeInteger;
}
else if (odr["type"].ToString() == "浮点型")
{
obj2[1] = esriFieldType.esriFieldTypeDouble;
}
else if (odr["type"].ToString() == "字符型")
{
obj2[1] = esriFieldType.esriFieldTypeString;
}
else if (odr["type"].ToString() == "图元")
{
obj2[1] = esriFieldType.esriFieldTypeGeometry;
}
obj2[2] = odr["LENGTH"].ToString();
if (odr["ISNULL"].ToString() == "是")
{
obj2[3] = true;
}
else
{
obj2[3] = false;
}
if (obj1[1].ToString() != obj2[1].ToString()
|| obj1[2].ToString() != obj2[2].ToString()
|| obj1[3].ToString() != obj2[3].ToString())
{
result = false;
break;
}
}
else
{
result = false;
break;
}
}
return result;
}
3.增加目录,把目录下的所有MDB文件加载进来,在控件中显示这些文件的相关信息。
[csharp] view
plaincopy
/// <summary>
/// 增加目录,把目录下的所有MDB文件加载进来
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void addDirectoryBtn_Click(object sender, EventArgs e)
{
FolderBrowserDialog folder = new FolderBrowserDialog();
if (folder.ShowDialog() == DialogResult.OK)
{
string strPath = folder.SelectedPath;
if (strPath == "")
{
return;
}
string[] fileNames = Directory.GetFiles(strPath);
string strTemp;
foreach (string str in fileNames)
{
strTemp = str.Remove(0, str.LastIndexOf('\\') + 1);
if (strTemp.Substring(strTemp.IndexOf('.')) == ".mdb")
{
if (!fileIsExist(strTemp))
{
object[] obj = new object[2];
//strTemp = strTemp.Remove(strTemp.IndexOf('.'));
obj[0] = strTemp;
obj[1] = strPath;
dataGridViewX1.Rows.Add(obj);
addTableNameToDataGridView(str);
}
}
}
}
}
这个函数依次变量目录下的所有MDB文件,然后调用函数fileIsExist判断文件是否已经加载了,最后调用前面介绍的函数addTableNameToDataGridView把具体的文件相关信息加载到控件中显示。
4.从MDB文件信息显示控件中删除一个文件,并联动删除在另一个控件中的相应的表结构信息。
[csharp] view
plaincopy
/// <summary>
/// 从DataGridViewX1中删除MDB文件,并删除DataGridViewX2中属于这个MDB文件的表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void delFileBtn_Click(object sender, EventArgs e)
{
if (dataGridViewX1.CurrentRow != null)
{
string strFileName = dataGridViewX1.Rows[dataGridViewX1.CurrentRow.Index].Cells[1].Value.ToString() + "\\" +
dataGridViewX1.Rows[dataGridViewX1.CurrentRow.Index].Cells[0].Value.ToString();
//打开mdb文件所在的工作空间
IWorkspaceFactory wf = new AccessWorkspaceFactory();
IWorkspace2 pAccessW = wf.OpenFromFile(strFileName, 0) as IWorkspace2;
int count = dataGridViewX2.Rows.Count;
for (int i = count-1; i >=0; --i)
{
string strName = dataGridViewX2.Rows[i].Cells[1].Value.ToString();
if (pAccessW.get_NameExists(esriDatasetType.esriDTFeatureClass, strName)
|| pAccessW.get_NameExists(esriDatasetType.esriDTTable,strName))
{
dataGridViewX2.Rows.Remove(dataGridViewX2.Rows[i]);
}
}
dataGridViewX1.Rows.Remove(dataGridViewX1.CurrentRow);
}
else
{
MessageBox.Show("请选择一个要删除的行!");
}
}
5.通过MDB文件找到要素类或者属性表,查找的方法就是依次遍历然后对比给定的表名称。
[csharp] view
plaincopy
/// <summary>
/// 通过MDB文件找到要素类或值属性表
/// </summary>
/// <param name="fileName">MDB文件名</param>
/// <param name="strTableName">要素类名称或属性表名</param>
/// <returns></returns>
private object FindTableInMDB(string fileName, string strTableName)
{
//打开mdb文件所在的工作空间
IWorkspaceFactory wf = new AccessWorkspaceFactory();
IFeatureWorkspace pFeatureWorkspaceMDB = wf.OpenFromFile(fileName, 0) as IFeatureWorkspace;
IWorkspace pWorkspaceMDB = pFeatureWorkspaceMDB as IWorkspace;
//1.遍历mdb的每一个要素集
IEnumDataset enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTFeatureDataset);
IFeatureDataset featureDs = enumDataset.Next() as IFeatureDataset;
while (featureDs != null)
{
IFeatureClass pFeatureClass;
IFeatureClassContainer fcContainer = featureDs as IFeatureClassContainer;
for (int i = 0; i < fcContainer.ClassCount; i++)
{
pFeatureClass = fcContainer.get_Class(i);
if (pFeatureClass.AliasName.ToLower() == strTableName.ToLower())
{
return pFeatureClass;
}
}
featureDs = enumDataset.Next() as IFeatureDataset;
}
//2.遍历mdb的每一个独立要素类
enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTFeatureClass);
IDataset dataset = enumDataset.Next();
while (dataset != null)
{
IFeatureClass pFeatureClass = dataset as IFeatureClass;
if (pFeatureClass.AliasName.ToLower() == strTableName.ToLower())
{
return pFeatureClass;
}
dataset = enumDataset.Next();
}
//3.遍历mdb的每一个属性表
enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTTable);
dataset = enumDataset.Next();
while (dataset != null)
{
ITable t = dataset as ITable;
if (dataset.Name.ToLower() == strTableName.ToLower())
{
return t;
}
dataset = enumDataset.Next();
}
return null;
}
6.转换所有导入的MDB文件中的数据到SDE数据库中。
[csharp] view
plaincopy
/// <summary>
/// 转换MDB文件中的数据到SDE数据库中
/// </summary>
/// <param name="fileName">MDB文件名</param>
private void mdbfileToSDE(string fileName)
{
//打开mdb文件所在的工作空间
IWorkspaceFactory wf = new AccessWorkspaceFactory();
IWorkspace pWorkspaceMDB = wf.OpenFromFile(fileName, 0);
IWorkspace2 pW2 = pWorkspaceMDB as IWorkspace2;
//查找属于本文件中的表并导入
for (int i=0; i<dataGridViewX2.Rows.Count; ++i)
{
string strSourceTableName = dataGridViewX2.Rows[i].Cells[1].Value.ToString();
string strTargetTableName = dataGridViewX2.Rows[i].Cells[2].Value.ToString();
//此表是否存在此MDB文件IFeatureClass
if (pW2.get_NameExists(esriDatasetType.esriDTFeatureClass, strSourceTableName))
{
//是否选择需要导入
if (bool.Parse(dataGridViewX2.Rows[i].Cells[0].Value.ToString()))
{
//SDE中是否存在此表了,是就添加记录,否则新建游离图层
if (dataGridViewX2.Rows[i].Cells[3].Value.ToString().Trim() == "否")
{
MapOperation.ConvertFeatureClass(pWorkspaceMDB, pWorkspaceSDE as IWorkspace,
strSourceTableName, strTargetTableName, 0);
//插入一条记录到layer中去
IFeatureWorkspace pFW = pWorkspaceMDB as IFeatureWorkspace;
IFeatureClass pFC = pFW.OpenFeatureClass(strTargetTableName);
SqlHelper sh = new SqlHelper();
string sql = "select max(ID) from layer";
OracleDataReader odr = sh.ReturnDataReader(sql);
int result = 0;
if (odr.Read())
{
result = int.Parse(odr[0].ToString());
result += 1;
}
Hashtable ht = new Hashtable();
ht.Add("ID", result);
ht.Add("PID", 2025);
ht.Add("TABLE_NAME", strTargetTableName);
ht.Add("TABLE_MAPNAME", strTargetTableName);
ht.Add("DESCRIPTION", "无辅助信息!");
if (pFC.ShapeType == esriGeometryType.esriGeometryPoint
|| pFC.ShapeType == esriGeometryType.esriGeometryMultipoint)
{
ht.Add("TYPE", "PT");
}
else if (pFC.ShapeType == esriGeometryType.esriGeometryLine
|| pFC.ShapeType == esriGeometryType.esriGeometryPolyline)
{
ht.Add("TYPE", "PL");
}
else if (pFC.ShapeType == esriGeometryType.esriGeometryPolygon)
{
ht.Add("TYPE", "PY");
}
else
{
ht.Add("TYPE", "PY");
}
sh.Insert("layer", ht);
}
else
{
AddMDBFeatureClassToSDE(pWorkspaceMDB, pWorkspaceSDE as IWorkspace,
strSourceTableName, strTargetTableName);
}
}
}
//ITable
else if (pW2.get_NameExists(esriDatasetType.esriDTTable, strSourceTableName))
{
//是否选择需要导入
if (bool.Parse(dataGridViewX2.Rows[i].Cells[0].Value.ToString()))
{
//SDE中是否存在此表了,是就添加记录,否则新建游离图层
if (dataGridViewX2.Rows[i].Cells[3].Value.ToString().Trim() == "否")
{
ITable pSourceT = (ITable)FindTableInMDB(fileName, strSourceTableName);
ITable pTargetT = pWorkspaceSDE.CreateTable(strSourceTableName, pSourceT.Fields,
null, null, "");
FusedIndexTable(ref pSourceT, ref pTargetT);
//插入一条记录到layer中去
SqlHelper sh = new SqlHelper();
string sql = "select max(ID) from layer";
OracleDataReader odr = sh.ReturnDataReader(sql);
int result = 0;
if (odr.Read())
{
result = int.Parse(odr[0].ToString());
result += 1;
}
Hashtable ht = new Hashtable();
ht.Add("ID", result);
ht.Add("PID", 2024);
ht.Add("TABLE_NAME", strTargetTableName);
ht.Add("TABLE_MAPNAME", strTargetTableName);
ht.Add("DESCRIPTION", "无辅助信息!");
ht.Add("TYPE", "PT");
sh.Insert("layer", ht);
}
else
{
ITable pTargetT = pWorkspaceSDE.OpenTable(strTargetTableName);
ITable pSourceT = (ITable)FindTableInMDB(fileName, strSourceTableName);
FusedIndexTable(ref pSourceT, ref pTargetT);
}
}
}
}
}
从上面代码可以看出,在导入的时候分为属性表和空间表,因为空间表和属性表导入方法不同。在导入的时候又要首先判断是否在Oracle数据库中是否已经存在对应的表,如果没有就需要创建一个新表来保持导入的数据,这个功能在函数MapOperation类ConvertFeatureClass实现,这个函数已经讲解,完成导入以后因为是新建的表结构,就需要在数据字典中添加一条记录,记录的内容就是表的相关信息。如果空间表已经存在那么就调用函数AddMDBFeatureClassToSDE完成数据的追加导入,这个函数实现如下:
[csharp] view
plaincopy
/// <summary>
/// 将mdb中要素类转换追加到sde数据库已有的要素类中
/// </summary>
/// <param name="sourceWorkspace"></param>
/// <param name="targetWorkspace"></param>
/// <param name="nameOfSourceFeatureClass"></param>
/// <param name="nameOfTargetFeatureClass"></param>
public void AddMDBFeatureClassToSDE(IWorkspace sourceWorkspace, IWorkspace targetWorkspace,
string nameOfSourceFeatureClass, string nameOfTargetFeatureClass)
{
IFeatureWorkspace pSourceFW = sourceWorkspace as IFeatureWorkspace;
IFeatureClass pSourceFc = pSourceFW.OpenFeatureClass(nameOfSourceFeatureClass);
IFeatureWorkspace pTargetFW = targetWorkspace as IFeatureWorkspace;
IFeatureClass pTargetFc = pTargetFW.OpenFeatureClass(nameOfTargetFeatureClass);
mdb2fc(pSourceFc, pTargetFc);
/*IFeatureWorkspace pSourceFW = sourceWorkspace as IFeatureWorkspace;
ITable pSourceTable = pSourceFW.OpenTable(nameOfSourceFeatureClass);
IFeatureWorkspace pTargerFW = targetWorkspace as IFeatureWorkspace;
ITable pTargetTable = pTargerFW.OpenTable(nameOfTargetFeatureClass);
FusedIndexTable(ref pSourceTable, ref pTargetTable);*/
}
这个函数又调用mdb2fc函数一个一个字段和值的完成数据导入,继续看这个函数的实现:
[csharp] view
plaincopy
/// <summary>
/// 追加要素到SDE的featureclass中
/// </summary>
/// <param name="pSourceFc"></param>
/// <param name="pTargetFc"></param>
private void mdb2fc(IFeatureClass pSourceFc, IFeatureClass pTargetFc)
{
IFeatureCursor pFeaCursor = pSourceFc.Search(null, false);
IFeature pFeature = pFeaCursor.NextFeature();
IField pField = new FieldClass();
int iIndex = 0;
while (pFeature != null)
{
IFeature tempFeature = pTargetFc.CreateFeature();
tempFeature.Shape = pFeature.Shape;
try
{
//添加字段值
for (int j = 0; j < pSourceFc.Fields.FieldCount; j++)
{
pField = pSourceFc.Fields.get_Field(j);
iIndex = tempFeature.Fields.FindField(pField.Name);
if (pField.Editable && iIndex != -1)
{
tempFeature.set_Value(iIndex, pFeature.get_Value(j));
}
}
tempFeature.Store();
}
catch (System.Exception ex)
{
MessageBox.Show("单要素写入异常!" + ex.Message, "提示");
return;
}
pFeature = pFeaCursor.NextFeature();
}
}
如果是属性表也要首先考虑是否在Oracle数据库存在表结构了,不存在同样需要先要创建一个新的表结构,并且在数据字典中添加一条表的相关信息的记录。创建表以后调用FusedIndexTable函数完成数据的具体导入,如果已经存在表结构那么就直接调用FusedIndexTable函数导入数据,这个函数实现如下所示:
[csharp] view
plaincopy
/// <summary>
/// 如果目的数据库中已经有表,则将新的记录追加进去
/// </summary>
/// <param name="FromTable"></param>
/// <param name="ToTable"></param>
private void FusedIndexTable(ref ITable FromTable, ref ITable ToTable)
{
if (FromTable == null || ToTable == null)
{
return;
}
IRow pFromRow;
ICursor pToCursor, pFromCursor;
IRowBuffer pToRowBuffer;
int pIndex;
pToRowBuffer = ToTable.CreateRowBuffer();
pToCursor = ToTable.Insert(true);
pFromCursor = FromTable.Search(null, false);
pFromRow = pFromCursor.NextRow();
while (pFromRow != null)
{
for (int i = 0; i < pFromRow.Fields.FieldCount; i++)
{
pIndex = pToRowBuffer.Fields.FindField(pFromRow.Fields.get_Field(i).Name.Trim());
if (pFromRow.Fields.get_Field(i).Editable && pIndex > -1)
{
pToRowBuffer.set_Value(pIndex, pFromRow.get_Value(i));
}
}
pToCursor.InsertRow(pToRowBuffer);
pFromRow = pFromCursor.NextRow();
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(pToCursor);
pFromRow = null;
pFromCursor = null;
pToRowBuffer = null;
}
7.点击完成按钮完成导入数据的功能,这种导入数据上上面介绍的那个函数mdbfileToSDE。
[html] view
plaincopy
/// <summary>
/// 完成按钮事件开始导入数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void finishBtn_Click(object sender, EventArgs e)
{
if (checkBoxX1.Checked)
{
MessageBox.Show("请选择空间参考系!");
return;
}
if (pWorkspaceSDE != null)
{
int fileCount = dataGridViewX1.Rows.Count;
for (int i = 0; i < fileCount; ++i)
{
string strFileName = dataGridViewX1.Rows[i].Cells[1].Value.ToString() + "\\" +
dataGridViewX1.Rows[i].Cells[0].Value.ToString();
//清空原表数据
if (checkBoxX2.Checked)
{
if (dataGridViewX2.Rows[i].Cells[3].Value.ToString().Trim() == "是")
{
string strTableName = dataGridViewX2.Rows[i].Cells[2].Value.ToString();
SqlHelper sh = new SqlHelper();
string sql = "delete from " + strTableName;
sh.ExecuteSQL(sql);
}
}
mdbfileToSDE(strFileName);
}
LogHelp.writeLog(FrmMain.username, "空间数据管理", "空间数据MDB格式转换导入成功");
MessageBox.Show("数据导入完成!");
}
Close();
}
在导入的时候根据导入的选项来决定具体怎样导入,例如是否检查控件参考系或者时候清除原表中已有的数据。
8.将mdb中的要素数据集转换到sde数据库中
[csharp] view
plaincopy
/// <summary>
/// 将mdb中的要素数据集转换到sde数据库中
/// </summary>
/// <param name="sourceWorkspace"></param>
/// <param name="targetWorkspace"></param>
/// <param name="nameOfSourceFeatureDataset"></param>
/// <param name="nameOfTargetFeatureDataset"></param>
public void ConvertMDBFeatureDatasetToSDE(IWorkspace sourceWorkspace, IWorkspace targetWorkspace,
string nameOfSourceFeatureDataset, string nameOfTargetFeatureDataset)
{
if (sourceWorkspace == null || targetWorkspace == null)
{
return;
}
//创建源工作空间名
IDataset sourceWorkspaceDataset = (IDataset)sourceWorkspace;
IWorkspaceName sourceWorkspaceName = (IWorkspaceName)sourceWorkspaceDataset.FullName;
//创建源数据集名
IFeatureDatasetName sourceFeatureDatasetName = new FeatureDatasetNameClass();
IDatasetName sourceDatasetName = (IDatasetName)sourceFeatureDatasetName;
sourceDatasetName.WorkspaceName = sourceWorkspaceName;
sourceDatasetName.Name = nameOfSourceFeatureDataset;
//创建目标工作空间名
IDataset targetWorkspaceDataset = (IDataset)targetWorkspace;
IWorkspaceName targetWorkspaceName = (IWorkspaceName)targetWorkspaceDataset.FullName;
//创建目标数据集名
IFeatureDatasetName targetFeatureDatasetName = new FeatureDatasetNameClass();
IDatasetName targetDatasetName = (IDatasetName)targetFeatureDatasetName;
targetDatasetName.WorkspaceName = targetWorkspaceName;
targetDatasetName.Name = nameOfTargetFeatureDataset;
//转换(复制)源数据集到目标数据集
IFeatureDataConverter featureDataConverter = new FeatureDataConverter();
featureDataConverter.ConvertFeatureDataset(sourceFeatureDatasetName,
targetFeatureDatasetName, null, "", 1000, 0);
}
9.当在表信息的控件显示列中选择一个表的时候就在另一个控件中显示表的字段相关信息。
[csharp] view
plaincopy
/// <summary>
/// 显示一个表中的字段信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dataGridViewX2_Click(object sender, EventArgs e)
{
dataGridViewX3.Rows.Clear();
if (dataGridViewX2.CurrentRow == null)
{
return;
}
int fileCount = dataGridViewX1.Rows.Count;
string strFileName;
for (int i = 0; i < fileCount; ++i)
{
strFileName = dataGridViewX1.Rows[i].Cells[1].Value.ToString() + "\\" +
dataGridViewX1.Rows[i].Cells[0].Value.ToString();
string strTableName = dataGridViewX2.CurrentRow.Cells[1].Value.ToString();
//打开mdb文件所在的工作空间
IWorkspaceFactory wf = new AccessWorkspaceFactory();
IFeatureWorkspace pFeatureWorkspaceMDB = wf.OpenFromFile(strFileName, 0) as IFeatureWorkspace;
IWorkspace pWorkspaceMDB = pFeatureWorkspaceMDB as IWorkspace;
//1.遍历mdb的每一个要素集
IEnumDataset enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTFeatureDataset);
IFeatureDataset featureDs = enumDataset.Next() as IFeatureDataset;
IFields pFs = null;
while (featureDs != null)
{
IFeatureClass pFC = null;
IFeatureClassContainer fcContainer = featureDs as IFeatureClassContainer;
for (int j = 0; j < fcContainer.ClassCount; j++)
{
if (fcContainer.get_Class(j).AliasName.ToLower() == strTableName.ToLower())
{
pFC = fcContainer.get_Class(j);
pFs = pFC.Fields;
break;
}
}
featureDs = enumDataset.Next() as IFeatureDataset;
}
//2.遍历mdb的每一个独立要素类
if (pFs == null)
{
IFeatureClass pFC = null;
enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTFeatureClass);
IDataset dataset = enumDataset.Next();
while (dataset != null)
{
pFC = dataset as IFeatureClass;
if (pFC.AliasName.ToLower() == strTableName.ToLower())
{
pFs = pFC.Fields;
break;
}
dataset = enumDataset.Next();
}
}
//3.遍历mdb的每一个属性表
if (pFs == null)
{
ITable tc = null;
enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTTable);
IDataset dataset = enumDataset.Next();
while (dataset != null)
{
tc = dataset as ITable;
if (dataset.Name.ToLower() == strTableName.ToLower())
{
pFs = tc.Fields;
break;
}
dataset = enumDataset.Next();
}
}
if (pFs != null)
{
object[] obj = new object[4];
for (int j = 0; j < pFs.FieldCount; ++j)
{
IField field = pFs.get_Field(j);
obj[0] = field.Name;
obj[1] = field.Name;
obj[2] = field.Type;
obj[3] = field.Length;
dataGridViewX3.Rows.Add(obj);
}
}
}
//判断所有的是否通过了检查,可以是人为的,也可能是自动检查,通过则使能完成按钮
//否则禁止完成按钮
bool isAll = true;
for (int i = 0; i < dataGridViewX2.Rows.Count; ++i)
{
if (!bool.Parse(dataGridViewX2.Rows[i].Cells[4].Value.ToString()))
{
isAll = false;
break;
}
}
if (isAll)
{
finishBtn.Enabled = true;
}
else
{
finishBtn.Enabled = false;
}
}
10.打开检查字段信息的对话框,具体检查的实现在以后单独一篇博客具体讲解。
[csharp] view
plaincopy
/// <summary>
/// 打开检查字段信息的对话框
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void checkFieldBtn_Click(object sender, EventArgs e)
{
int fileCount = dataGridViewX1.Rows.Count;
FrmCheckFiled fcf = new FrmCheckFiled();
for (int i = 0; i < fileCount; ++i)
{
string strFileName = dataGridViewX1.Rows[i].Cells[1].Value.ToString() + "\\" +
dataGridViewX1.Rows[i].Cells[0].Value.ToString();
fcf.AddDataToComboBox(strFileName);
}
fcf.pWorkspaceSDE = pWorkspaceSDE;
fcf.ShowDialog();
}
11.当表的名称信息改变时,对于是否在Oracle数据库中已存在的信息从新检查并更新显示信息
[csharp] view
plaincopy
/// <summary>
/// 当表的名称信息改变时,对于是否在Oracle数据库中已存在的信息从新检查并更新显示信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dataGridViewX2_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (dataGridViewX2.Rows.Count > 0)
{
//改变导入的目的表的名称后检查是否存在在数据库中
if (dataGridViewX2.Columns[e.ColumnIndex].HeaderText == "导入表名称")
{
SqlHelper sh = new SqlHelper();
string sql = "select table_name from jcsjk_layer l,jcsjk_element e where table_name='"
+ dataGridViewX2.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString().ToLower()
+ "' and e.id=l.pid and e.category='地震矢量数据'";
if (sh.GetRecordCount(sql) > 0)
{
dataGridViewX2.Rows[e.RowIndex].Cells[3].Value = "是";
}
else
{
dataGridViewX2.Rows[e.RowIndex].Cells[3].Value = "否";
}
}
}
}
12.总结
MDB空间数据格式的导入所有功能基本介绍完毕。还是检查字段相关信息最复杂。
和Shape相同的部分就不在讲解了,只讲解与Shape不同的实现部分!
1.添加一个MDB格式的空间数据文件到导入列表,并显示其相关信息。
[csharp] view
plaincopy
/// <summary>
/// 添加一个MDB格式的文件到导入控件列表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void addFileBtn_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
//打开MDB文件
string StrFilter = "MDB文件(.mdb) | *.mdb";
ofd.Filter = StrFilter;
string ImportMDBName;
if (ofd.ShowDialog() == DialogResult.OK)
{
ImportMDBName = ofd.FileName;
}
else
{
return;
}
//得到文件名和目录名
string ImportFileName = System.IO.Path.GetFileName(ImportMDBName);
string ImportFilePath = System.IO.Path.GetDirectoryName(ImportMDBName);
//检查文件是否已经存在DataGridView中,没有就加载到其中
if (!fileIsExist(ImportFileName))
{
object[] obj = new object[2];
obj[0] = ImportFileName;
obj[1] = ImportFilePath;
dataGridViewX1.Rows.Add(obj);
addTableNameToDataGridView(ImportMDBName);
}
}
这个函数又调用了一个专门用于检测文件是否已经被导入了的函数,实现如下:
[csharp] view
plaincopy
/// <summary>
/// 判断文件名是否已经存在在DataGridView中了
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
private bool fileIsExist(string filename)
{
bool result = false;
for (int i = 0; i < dataGridViewX1.Rows.Count; ++i)
{
if (filename == dataGridViewX1.Rows[i].Cells[0].Value.ToString())
{
result = true;
break;
}
}
return result;
}
2.读出一个MDB格式文件里所有的表相关信息并加载到控件中显示。
[csharp] view
plaincopy
/// <summary>
/// 读出一个MDB格式文件里所有的表相关信息并加载到控件中显示
/// </summary>
/// <param name="filename"></param>
private void addTableNameToDataGridView(string filename)
{
//打开mdb文件所在的工作空间
IWorkspaceFactory wf = new AccessWorkspaceFactory();
IFeatureWorkspace pAccessFW = wf.OpenFromFile(filename, 0) as IFeatureWorkspace;
IWorkspace pAccessW = pAccessFW as IWorkspace;
object[] obj = new object[5];
SqlHelper sh = new SqlHelper();
string sql = string.Empty;
//1.遍历mdb的每一个要素集,并加载表信息到DataGridViewX2中
IEnumDataset enumDataset = pAccessW.get_Datasets(esriDatasetType.esriDTFeatureDataset);
IFeatureDataset featureDs = enumDataset.Next() as IFeatureDataset;
while (featureDs != null)
{
IFeatureClass pFeatureClass;
IFeatureClassContainer fcContainer = featureDs as IFeatureClassContainer;
for (int i = 0; i < fcContainer.ClassCount; i++)
{
pFeatureClass = fcContainer.get_Class(i);
obj[0] = true;
obj[1] = pFeatureClass.AliasName;
obj[2] = pFeatureClass.AliasName;
sql = "select table_name from layer l,element e where table_name='"
+ pFeatureClass.AliasName.ToLower()
+ "' and e.id=l.pid and e.category='矢量数据'";
if (sh.GetRecordCount(sql) > 0)
{
obj[3] = "是";
}
else
{
obj[3] = "否";
}
//检查此表结构是否符合标准
if (CheckFields(pFeatureClass.Fields, pFeatureClass.AliasName))
{
obj[4] = true;
}
else
{
obj[4] = false;
}
dataGridViewX2.Rows.Add(obj);
}
featureDs = enumDataset.Next() as IFeatureDataset;
}
//2.遍历mdb的每一个独立要素类,,并加载表信息到DataGridViewX2中
enumDataset = pAccessW.get_Datasets(esriDatasetType.esriDTFeatureClass);
IDataset dataset = enumDataset.Next();
while (dataset != null)
{
IFeatureClass pFeatureClass = dataset as IFeatureClass;
obj[0] = true;
obj[1] = pFeatureClass.AliasName;
obj[2] = pFeatureClass.AliasName;
sql = "select table_name from layer l,element e where table_name='"
+ pFeatureClass.AliasName.ToLower()
+ "' and e.id=l.pid and e.category='矢量数据'";
if (sh.GetRecordCount(sql) > 0)
{
obj[3] = "是";
}
else
{
obj[3] = "否";
}
//检查此表结构是否符合标准
if (CheckFields(pFeatureClass.Fields, pFeatureClass.AliasName))
{
obj[4] = true;
}
else
{
obj[4] = false;
}
dataGridViewX2.Rows.Add(obj);
dataset = enumDataset.Next();
}
//3.遍历mdb的每一个属性表,,并加载表信息到DataGridViewX2中
enumDataset = pAccessW.get_Datasets(esriDatasetType.esriDTTable);
dataset = enumDataset.Next();
while (dataset != null)
{
ITable t = dataset as ITable;
obj[0] = true;
obj[1] = dataset.Name;
obj[2] = dataset.Name;
sql = "select table_name from layer l,element e where table_name='"
+ dataset.Name.ToLower()
+ "' and e.id=l.pid and e.category='矢量数据'";
if (sh.GetRecordCount(sql) > 0)
{
obj[3] = "是";
}
else
{
obj[3] = "否";
}
//检查此表结构是否符合标准
if (CheckFields(t.Fields, dataset.Name))
{
obj[4] = true;
}
else
{
obj[4] = false;
}
dataGridViewX2.Rows.Add(obj);
dataset = enumDataset.Next();
}
//判断所有的是否通过了检查,可以是人为的,也可能是自动检查,通过则使能完成按钮
//否则禁止完成按钮
bool isAll = true;
for (int i = 0; i < dataGridViewX2.Rows.Count; ++i )
{
if (!bool.Parse(dataGridViewX2.Rows[i].Cells[4].Value.ToString()))
{
isAll = false;
break;
}
}
if (isAll)
{
finishBtn.Enabled = true;
}
else
{
finishBtn.Enabled = false;
}
}
由上面的代码可以看出要读取出MDB文件中所有的表结构信息需要分三种情况,一、所有在数据集里面的表;二、独立(游离)的表;三、属性表。每读取一个表结构的信息就检测这个表的字段是否符合数据库中定义好的数据结构,完成这个功能是调用函数CheckFields,这个函数定义和实现如下所示:
[csharp] view
plaincopy
/// <summary>
/// 检查字段是否符合数据标准定义
/// </summary>
/// <param name="pSourceFileds">字段集</param>
/// <param name="strTableName">对应的标准名</param>
/// <returns></returns>
private bool CheckFields(IFields pSourceFileds, string strTableName)
{
SqlHelper sh = new SqlHelper();
string sql = "select * from fielddefine where table_name ='"
+ strTableName.ToUpper() + "' or table_name='" + strTableName.ToLower() + "'";
if (pSourceFileds.FieldCount != sh.GetRecordCount(sql))
{
return false;
}
bool result = true;
OracleDataReader odr = sh.ReturnDataReader(sql);
object[] obj1 = new object[4];
object[] obj2 = new object[4];
for (int i = 0; i < pSourceFileds.FieldCount; i++)
{
odr.Read();
if (pSourceFileds.FindField(odr["NAME"].ToString()) >= 0)
{
IField pSourceField = pSourceFileds.get_Field(pSourceFileds.FindField(odr["NAME"].ToString()));
obj1[0] = pSourceField.Name;
obj1[1] = pSourceField.Type;
obj1[2] = pSourceField.Length;
obj1[3] = pSourceField.IsNullable;
obj2[0] = odr["NAME"].ToString();
if (odr["TYPE"].ToString() == "RowID")
{
obj2[1] = esriFieldType.esriFieldTypeOID;
}
else if (odr["type"].ToString() == "整数型")
{
obj2[1] = esriFieldType.esriFieldTypeInteger;
}
else if (odr["type"].ToString() == "浮点型")
{
obj2[1] = esriFieldType.esriFieldTypeDouble;
}
else if (odr["type"].ToString() == "字符型")
{
obj2[1] = esriFieldType.esriFieldTypeString;
}
else if (odr["type"].ToString() == "图元")
{
obj2[1] = esriFieldType.esriFieldTypeGeometry;
}
obj2[2] = odr["LENGTH"].ToString();
if (odr["ISNULL"].ToString() == "是")
{
obj2[3] = true;
}
else
{
obj2[3] = false;
}
if (obj1[1].ToString() != obj2[1].ToString()
|| obj1[2].ToString() != obj2[2].ToString()
|| obj1[3].ToString() != obj2[3].ToString())
{
result = false;
break;
}
}
else
{
result = false;
break;
}
}
return result;
}
3.增加目录,把目录下的所有MDB文件加载进来,在控件中显示这些文件的相关信息。
[csharp] view
plaincopy
/// <summary>
/// 增加目录,把目录下的所有MDB文件加载进来
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void addDirectoryBtn_Click(object sender, EventArgs e)
{
FolderBrowserDialog folder = new FolderBrowserDialog();
if (folder.ShowDialog() == DialogResult.OK)
{
string strPath = folder.SelectedPath;
if (strPath == "")
{
return;
}
string[] fileNames = Directory.GetFiles(strPath);
string strTemp;
foreach (string str in fileNames)
{
strTemp = str.Remove(0, str.LastIndexOf('\\') + 1);
if (strTemp.Substring(strTemp.IndexOf('.')) == ".mdb")
{
if (!fileIsExist(strTemp))
{
object[] obj = new object[2];
//strTemp = strTemp.Remove(strTemp.IndexOf('.'));
obj[0] = strTemp;
obj[1] = strPath;
dataGridViewX1.Rows.Add(obj);
addTableNameToDataGridView(str);
}
}
}
}
}
这个函数依次变量目录下的所有MDB文件,然后调用函数fileIsExist判断文件是否已经加载了,最后调用前面介绍的函数addTableNameToDataGridView把具体的文件相关信息加载到控件中显示。
4.从MDB文件信息显示控件中删除一个文件,并联动删除在另一个控件中的相应的表结构信息。
[csharp] view
plaincopy
/// <summary>
/// 从DataGridViewX1中删除MDB文件,并删除DataGridViewX2中属于这个MDB文件的表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void delFileBtn_Click(object sender, EventArgs e)
{
if (dataGridViewX1.CurrentRow != null)
{
string strFileName = dataGridViewX1.Rows[dataGridViewX1.CurrentRow.Index].Cells[1].Value.ToString() + "\\" +
dataGridViewX1.Rows[dataGridViewX1.CurrentRow.Index].Cells[0].Value.ToString();
//打开mdb文件所在的工作空间
IWorkspaceFactory wf = new AccessWorkspaceFactory();
IWorkspace2 pAccessW = wf.OpenFromFile(strFileName, 0) as IWorkspace2;
int count = dataGridViewX2.Rows.Count;
for (int i = count-1; i >=0; --i)
{
string strName = dataGridViewX2.Rows[i].Cells[1].Value.ToString();
if (pAccessW.get_NameExists(esriDatasetType.esriDTFeatureClass, strName)
|| pAccessW.get_NameExists(esriDatasetType.esriDTTable,strName))
{
dataGridViewX2.Rows.Remove(dataGridViewX2.Rows[i]);
}
}
dataGridViewX1.Rows.Remove(dataGridViewX1.CurrentRow);
}
else
{
MessageBox.Show("请选择一个要删除的行!");
}
}
5.通过MDB文件找到要素类或者属性表,查找的方法就是依次遍历然后对比给定的表名称。
[csharp] view
plaincopy
/// <summary>
/// 通过MDB文件找到要素类或值属性表
/// </summary>
/// <param name="fileName">MDB文件名</param>
/// <param name="strTableName">要素类名称或属性表名</param>
/// <returns></returns>
private object FindTableInMDB(string fileName, string strTableName)
{
//打开mdb文件所在的工作空间
IWorkspaceFactory wf = new AccessWorkspaceFactory();
IFeatureWorkspace pFeatureWorkspaceMDB = wf.OpenFromFile(fileName, 0) as IFeatureWorkspace;
IWorkspace pWorkspaceMDB = pFeatureWorkspaceMDB as IWorkspace;
//1.遍历mdb的每一个要素集
IEnumDataset enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTFeatureDataset);
IFeatureDataset featureDs = enumDataset.Next() as IFeatureDataset;
while (featureDs != null)
{
IFeatureClass pFeatureClass;
IFeatureClassContainer fcContainer = featureDs as IFeatureClassContainer;
for (int i = 0; i < fcContainer.ClassCount; i++)
{
pFeatureClass = fcContainer.get_Class(i);
if (pFeatureClass.AliasName.ToLower() == strTableName.ToLower())
{
return pFeatureClass;
}
}
featureDs = enumDataset.Next() as IFeatureDataset;
}
//2.遍历mdb的每一个独立要素类
enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTFeatureClass);
IDataset dataset = enumDataset.Next();
while (dataset != null)
{
IFeatureClass pFeatureClass = dataset as IFeatureClass;
if (pFeatureClass.AliasName.ToLower() == strTableName.ToLower())
{
return pFeatureClass;
}
dataset = enumDataset.Next();
}
//3.遍历mdb的每一个属性表
enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTTable);
dataset = enumDataset.Next();
while (dataset != null)
{
ITable t = dataset as ITable;
if (dataset.Name.ToLower() == strTableName.ToLower())
{
return t;
}
dataset = enumDataset.Next();
}
return null;
}
6.转换所有导入的MDB文件中的数据到SDE数据库中。
[csharp] view
plaincopy
/// <summary>
/// 转换MDB文件中的数据到SDE数据库中
/// </summary>
/// <param name="fileName">MDB文件名</param>
private void mdbfileToSDE(string fileName)
{
//打开mdb文件所在的工作空间
IWorkspaceFactory wf = new AccessWorkspaceFactory();
IWorkspace pWorkspaceMDB = wf.OpenFromFile(fileName, 0);
IWorkspace2 pW2 = pWorkspaceMDB as IWorkspace2;
//查找属于本文件中的表并导入
for (int i=0; i<dataGridViewX2.Rows.Count; ++i)
{
string strSourceTableName = dataGridViewX2.Rows[i].Cells[1].Value.ToString();
string strTargetTableName = dataGridViewX2.Rows[i].Cells[2].Value.ToString();
//此表是否存在此MDB文件IFeatureClass
if (pW2.get_NameExists(esriDatasetType.esriDTFeatureClass, strSourceTableName))
{
//是否选择需要导入
if (bool.Parse(dataGridViewX2.Rows[i].Cells[0].Value.ToString()))
{
//SDE中是否存在此表了,是就添加记录,否则新建游离图层
if (dataGridViewX2.Rows[i].Cells[3].Value.ToString().Trim() == "否")
{
MapOperation.ConvertFeatureClass(pWorkspaceMDB, pWorkspaceSDE as IWorkspace,
strSourceTableName, strTargetTableName, 0);
//插入一条记录到layer中去
IFeatureWorkspace pFW = pWorkspaceMDB as IFeatureWorkspace;
IFeatureClass pFC = pFW.OpenFeatureClass(strTargetTableName);
SqlHelper sh = new SqlHelper();
string sql = "select max(ID) from layer";
OracleDataReader odr = sh.ReturnDataReader(sql);
int result = 0;
if (odr.Read())
{
result = int.Parse(odr[0].ToString());
result += 1;
}
Hashtable ht = new Hashtable();
ht.Add("ID", result);
ht.Add("PID", 2025);
ht.Add("TABLE_NAME", strTargetTableName);
ht.Add("TABLE_MAPNAME", strTargetTableName);
ht.Add("DESCRIPTION", "无辅助信息!");
if (pFC.ShapeType == esriGeometryType.esriGeometryPoint
|| pFC.ShapeType == esriGeometryType.esriGeometryMultipoint)
{
ht.Add("TYPE", "PT");
}
else if (pFC.ShapeType == esriGeometryType.esriGeometryLine
|| pFC.ShapeType == esriGeometryType.esriGeometryPolyline)
{
ht.Add("TYPE", "PL");
}
else if (pFC.ShapeType == esriGeometryType.esriGeometryPolygon)
{
ht.Add("TYPE", "PY");
}
else
{
ht.Add("TYPE", "PY");
}
sh.Insert("layer", ht);
}
else
{
AddMDBFeatureClassToSDE(pWorkspaceMDB, pWorkspaceSDE as IWorkspace,
strSourceTableName, strTargetTableName);
}
}
}
//ITable
else if (pW2.get_NameExists(esriDatasetType.esriDTTable, strSourceTableName))
{
//是否选择需要导入
if (bool.Parse(dataGridViewX2.Rows[i].Cells[0].Value.ToString()))
{
//SDE中是否存在此表了,是就添加记录,否则新建游离图层
if (dataGridViewX2.Rows[i].Cells[3].Value.ToString().Trim() == "否")
{
ITable pSourceT = (ITable)FindTableInMDB(fileName, strSourceTableName);
ITable pTargetT = pWorkspaceSDE.CreateTable(strSourceTableName, pSourceT.Fields,
null, null, "");
FusedIndexTable(ref pSourceT, ref pTargetT);
//插入一条记录到layer中去
SqlHelper sh = new SqlHelper();
string sql = "select max(ID) from layer";
OracleDataReader odr = sh.ReturnDataReader(sql);
int result = 0;
if (odr.Read())
{
result = int.Parse(odr[0].ToString());
result += 1;
}
Hashtable ht = new Hashtable();
ht.Add("ID", result);
ht.Add("PID", 2024);
ht.Add("TABLE_NAME", strTargetTableName);
ht.Add("TABLE_MAPNAME", strTargetTableName);
ht.Add("DESCRIPTION", "无辅助信息!");
ht.Add("TYPE", "PT");
sh.Insert("layer", ht);
}
else
{
ITable pTargetT = pWorkspaceSDE.OpenTable(strTargetTableName);
ITable pSourceT = (ITable)FindTableInMDB(fileName, strSourceTableName);
FusedIndexTable(ref pSourceT, ref pTargetT);
}
}
}
}
}
从上面代码可以看出,在导入的时候分为属性表和空间表,因为空间表和属性表导入方法不同。在导入的时候又要首先判断是否在Oracle数据库中是否已经存在对应的表,如果没有就需要创建一个新表来保持导入的数据,这个功能在函数MapOperation类ConvertFeatureClass实现,这个函数已经讲解,完成导入以后因为是新建的表结构,就需要在数据字典中添加一条记录,记录的内容就是表的相关信息。如果空间表已经存在那么就调用函数AddMDBFeatureClassToSDE完成数据的追加导入,这个函数实现如下:
[csharp] view
plaincopy
/// <summary>
/// 将mdb中要素类转换追加到sde数据库已有的要素类中
/// </summary>
/// <param name="sourceWorkspace"></param>
/// <param name="targetWorkspace"></param>
/// <param name="nameOfSourceFeatureClass"></param>
/// <param name="nameOfTargetFeatureClass"></param>
public void AddMDBFeatureClassToSDE(IWorkspace sourceWorkspace, IWorkspace targetWorkspace,
string nameOfSourceFeatureClass, string nameOfTargetFeatureClass)
{
IFeatureWorkspace pSourceFW = sourceWorkspace as IFeatureWorkspace;
IFeatureClass pSourceFc = pSourceFW.OpenFeatureClass(nameOfSourceFeatureClass);
IFeatureWorkspace pTargetFW = targetWorkspace as IFeatureWorkspace;
IFeatureClass pTargetFc = pTargetFW.OpenFeatureClass(nameOfTargetFeatureClass);
mdb2fc(pSourceFc, pTargetFc);
/*IFeatureWorkspace pSourceFW = sourceWorkspace as IFeatureWorkspace;
ITable pSourceTable = pSourceFW.OpenTable(nameOfSourceFeatureClass);
IFeatureWorkspace pTargerFW = targetWorkspace as IFeatureWorkspace;
ITable pTargetTable = pTargerFW.OpenTable(nameOfTargetFeatureClass);
FusedIndexTable(ref pSourceTable, ref pTargetTable);*/
}
这个函数又调用mdb2fc函数一个一个字段和值的完成数据导入,继续看这个函数的实现:
[csharp] view
plaincopy
/// <summary>
/// 追加要素到SDE的featureclass中
/// </summary>
/// <param name="pSourceFc"></param>
/// <param name="pTargetFc"></param>
private void mdb2fc(IFeatureClass pSourceFc, IFeatureClass pTargetFc)
{
IFeatureCursor pFeaCursor = pSourceFc.Search(null, false);
IFeature pFeature = pFeaCursor.NextFeature();
IField pField = new FieldClass();
int iIndex = 0;
while (pFeature != null)
{
IFeature tempFeature = pTargetFc.CreateFeature();
tempFeature.Shape = pFeature.Shape;
try
{
//添加字段值
for (int j = 0; j < pSourceFc.Fields.FieldCount; j++)
{
pField = pSourceFc.Fields.get_Field(j);
iIndex = tempFeature.Fields.FindField(pField.Name);
if (pField.Editable && iIndex != -1)
{
tempFeature.set_Value(iIndex, pFeature.get_Value(j));
}
}
tempFeature.Store();
}
catch (System.Exception ex)
{
MessageBox.Show("单要素写入异常!" + ex.Message, "提示");
return;
}
pFeature = pFeaCursor.NextFeature();
}
}
如果是属性表也要首先考虑是否在Oracle数据库存在表结构了,不存在同样需要先要创建一个新的表结构,并且在数据字典中添加一条表的相关信息的记录。创建表以后调用FusedIndexTable函数完成数据的具体导入,如果已经存在表结构那么就直接调用FusedIndexTable函数导入数据,这个函数实现如下所示:
[csharp] view
plaincopy
/// <summary>
/// 如果目的数据库中已经有表,则将新的记录追加进去
/// </summary>
/// <param name="FromTable"></param>
/// <param name="ToTable"></param>
private void FusedIndexTable(ref ITable FromTable, ref ITable ToTable)
{
if (FromTable == null || ToTable == null)
{
return;
}
IRow pFromRow;
ICursor pToCursor, pFromCursor;
IRowBuffer pToRowBuffer;
int pIndex;
pToRowBuffer = ToTable.CreateRowBuffer();
pToCursor = ToTable.Insert(true);
pFromCursor = FromTable.Search(null, false);
pFromRow = pFromCursor.NextRow();
while (pFromRow != null)
{
for (int i = 0; i < pFromRow.Fields.FieldCount; i++)
{
pIndex = pToRowBuffer.Fields.FindField(pFromRow.Fields.get_Field(i).Name.Trim());
if (pFromRow.Fields.get_Field(i).Editable && pIndex > -1)
{
pToRowBuffer.set_Value(pIndex, pFromRow.get_Value(i));
}
}
pToCursor.InsertRow(pToRowBuffer);
pFromRow = pFromCursor.NextRow();
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(pToCursor);
pFromRow = null;
pFromCursor = null;
pToRowBuffer = null;
}
7.点击完成按钮完成导入数据的功能,这种导入数据上上面介绍的那个函数mdbfileToSDE。
[html] view
plaincopy
/// <summary>
/// 完成按钮事件开始导入数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void finishBtn_Click(object sender, EventArgs e)
{
if (checkBoxX1.Checked)
{
MessageBox.Show("请选择空间参考系!");
return;
}
if (pWorkspaceSDE != null)
{
int fileCount = dataGridViewX1.Rows.Count;
for (int i = 0; i < fileCount; ++i)
{
string strFileName = dataGridViewX1.Rows[i].Cells[1].Value.ToString() + "\\" +
dataGridViewX1.Rows[i].Cells[0].Value.ToString();
//清空原表数据
if (checkBoxX2.Checked)
{
if (dataGridViewX2.Rows[i].Cells[3].Value.ToString().Trim() == "是")
{
string strTableName = dataGridViewX2.Rows[i].Cells[2].Value.ToString();
SqlHelper sh = new SqlHelper();
string sql = "delete from " + strTableName;
sh.ExecuteSQL(sql);
}
}
mdbfileToSDE(strFileName);
}
LogHelp.writeLog(FrmMain.username, "空间数据管理", "空间数据MDB格式转换导入成功");
MessageBox.Show("数据导入完成!");
}
Close();
}
在导入的时候根据导入的选项来决定具体怎样导入,例如是否检查控件参考系或者时候清除原表中已有的数据。
8.将mdb中的要素数据集转换到sde数据库中
[csharp] view
plaincopy
/// <summary>
/// 将mdb中的要素数据集转换到sde数据库中
/// </summary>
/// <param name="sourceWorkspace"></param>
/// <param name="targetWorkspace"></param>
/// <param name="nameOfSourceFeatureDataset"></param>
/// <param name="nameOfTargetFeatureDataset"></param>
public void ConvertMDBFeatureDatasetToSDE(IWorkspace sourceWorkspace, IWorkspace targetWorkspace,
string nameOfSourceFeatureDataset, string nameOfTargetFeatureDataset)
{
if (sourceWorkspace == null || targetWorkspace == null)
{
return;
}
//创建源工作空间名
IDataset sourceWorkspaceDataset = (IDataset)sourceWorkspace;
IWorkspaceName sourceWorkspaceName = (IWorkspaceName)sourceWorkspaceDataset.FullName;
//创建源数据集名
IFeatureDatasetName sourceFeatureDatasetName = new FeatureDatasetNameClass();
IDatasetName sourceDatasetName = (IDatasetName)sourceFeatureDatasetName;
sourceDatasetName.WorkspaceName = sourceWorkspaceName;
sourceDatasetName.Name = nameOfSourceFeatureDataset;
//创建目标工作空间名
IDataset targetWorkspaceDataset = (IDataset)targetWorkspace;
IWorkspaceName targetWorkspaceName = (IWorkspaceName)targetWorkspaceDataset.FullName;
//创建目标数据集名
IFeatureDatasetName targetFeatureDatasetName = new FeatureDatasetNameClass();
IDatasetName targetDatasetName = (IDatasetName)targetFeatureDatasetName;
targetDatasetName.WorkspaceName = targetWorkspaceName;
targetDatasetName.Name = nameOfTargetFeatureDataset;
//转换(复制)源数据集到目标数据集
IFeatureDataConverter featureDataConverter = new FeatureDataConverter();
featureDataConverter.ConvertFeatureDataset(sourceFeatureDatasetName,
targetFeatureDatasetName, null, "", 1000, 0);
}
9.当在表信息的控件显示列中选择一个表的时候就在另一个控件中显示表的字段相关信息。
[csharp] view
plaincopy
/// <summary>
/// 显示一个表中的字段信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dataGridViewX2_Click(object sender, EventArgs e)
{
dataGridViewX3.Rows.Clear();
if (dataGridViewX2.CurrentRow == null)
{
return;
}
int fileCount = dataGridViewX1.Rows.Count;
string strFileName;
for (int i = 0; i < fileCount; ++i)
{
strFileName = dataGridViewX1.Rows[i].Cells[1].Value.ToString() + "\\" +
dataGridViewX1.Rows[i].Cells[0].Value.ToString();
string strTableName = dataGridViewX2.CurrentRow.Cells[1].Value.ToString();
//打开mdb文件所在的工作空间
IWorkspaceFactory wf = new AccessWorkspaceFactory();
IFeatureWorkspace pFeatureWorkspaceMDB = wf.OpenFromFile(strFileName, 0) as IFeatureWorkspace;
IWorkspace pWorkspaceMDB = pFeatureWorkspaceMDB as IWorkspace;
//1.遍历mdb的每一个要素集
IEnumDataset enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTFeatureDataset);
IFeatureDataset featureDs = enumDataset.Next() as IFeatureDataset;
IFields pFs = null;
while (featureDs != null)
{
IFeatureClass pFC = null;
IFeatureClassContainer fcContainer = featureDs as IFeatureClassContainer;
for (int j = 0; j < fcContainer.ClassCount; j++)
{
if (fcContainer.get_Class(j).AliasName.ToLower() == strTableName.ToLower())
{
pFC = fcContainer.get_Class(j);
pFs = pFC.Fields;
break;
}
}
featureDs = enumDataset.Next() as IFeatureDataset;
}
//2.遍历mdb的每一个独立要素类
if (pFs == null)
{
IFeatureClass pFC = null;
enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTFeatureClass);
IDataset dataset = enumDataset.Next();
while (dataset != null)
{
pFC = dataset as IFeatureClass;
if (pFC.AliasName.ToLower() == strTableName.ToLower())
{
pFs = pFC.Fields;
break;
}
dataset = enumDataset.Next();
}
}
//3.遍历mdb的每一个属性表
if (pFs == null)
{
ITable tc = null;
enumDataset = pWorkspaceMDB.get_Datasets(esriDatasetType.esriDTTable);
IDataset dataset = enumDataset.Next();
while (dataset != null)
{
tc = dataset as ITable;
if (dataset.Name.ToLower() == strTableName.ToLower())
{
pFs = tc.Fields;
break;
}
dataset = enumDataset.Next();
}
}
if (pFs != null)
{
object[] obj = new object[4];
for (int j = 0; j < pFs.FieldCount; ++j)
{
IField field = pFs.get_Field(j);
obj[0] = field.Name;
obj[1] = field.Name;
obj[2] = field.Type;
obj[3] = field.Length;
dataGridViewX3.Rows.Add(obj);
}
}
}
//判断所有的是否通过了检查,可以是人为的,也可能是自动检查,通过则使能完成按钮
//否则禁止完成按钮
bool isAll = true;
for (int i = 0; i < dataGridViewX2.Rows.Count; ++i)
{
if (!bool.Parse(dataGridViewX2.Rows[i].Cells[4].Value.ToString()))
{
isAll = false;
break;
}
}
if (isAll)
{
finishBtn.Enabled = true;
}
else
{
finishBtn.Enabled = false;
}
}
10.打开检查字段信息的对话框,具体检查的实现在以后单独一篇博客具体讲解。
[csharp] view
plaincopy
/// <summary>
/// 打开检查字段信息的对话框
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void checkFieldBtn_Click(object sender, EventArgs e)
{
int fileCount = dataGridViewX1.Rows.Count;
FrmCheckFiled fcf = new FrmCheckFiled();
for (int i = 0; i < fileCount; ++i)
{
string strFileName = dataGridViewX1.Rows[i].Cells[1].Value.ToString() + "\\" +
dataGridViewX1.Rows[i].Cells[0].Value.ToString();
fcf.AddDataToComboBox(strFileName);
}
fcf.pWorkspaceSDE = pWorkspaceSDE;
fcf.ShowDialog();
}
11.当表的名称信息改变时,对于是否在Oracle数据库中已存在的信息从新检查并更新显示信息
[csharp] view
plaincopy
/// <summary>
/// 当表的名称信息改变时,对于是否在Oracle数据库中已存在的信息从新检查并更新显示信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void dataGridViewX2_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (dataGridViewX2.Rows.Count > 0)
{
//改变导入的目的表的名称后检查是否存在在数据库中
if (dataGridViewX2.Columns[e.ColumnIndex].HeaderText == "导入表名称")
{
SqlHelper sh = new SqlHelper();
string sql = "select table_name from jcsjk_layer l,jcsjk_element e where table_name='"
+ dataGridViewX2.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString().ToLower()
+ "' and e.id=l.pid and e.category='地震矢量数据'";
if (sh.GetRecordCount(sql) > 0)
{
dataGridViewX2.Rows[e.RowIndex].Cells[3].Value = "是";
}
else
{
dataGridViewX2.Rows[e.RowIndex].Cells[3].Value = "否";
}
}
}
}
12.总结
MDB空间数据格式的导入所有功能基本介绍完毕。还是检查字段相关信息最复杂。
相关文章推荐
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台十(C#开发)-空间数据导入RDBMS上-MDB格式
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台十(C#开发)-空间数据导入RDBMS上-MDB格式
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台九(C#开发)-空间数据导入RDBMS上-Shape格式
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台九(C#开发)-空间数据导入RDBMS上-Shape格式
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台九(C#开发)-空间数据导入RDBMS上-Shape格式
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台一(C#开发)
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台五(C#开发)-通用工具类
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台(C#开发)-AE常用操作代码
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台八(C#开发)-图层分类标准定义
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台十三(C#开发)-空间数据导出
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台一(C#开发)-系统功能介绍及展示
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台(C#开发)ArcGIS相关知识补充学习
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台(C#开发)-AE常用操作代码
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台八(C#开发)-图层分类标准定义
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台二(C#开发)
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台六(C#开发)-空间数据操作类
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台十三(C#开发)-空间数据导出
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台二(C#开发)-登录功能模块
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台(C#开发)-AE常用操作代码
- 基于ArcGIS10.0和Oracle10g的空间数据管理平台十二(C#开发)-日志管理