本文内容
- 背景
- 开发环境
- 问题描述
- 解决方案
背景
08 年毕业时,参加一个项目,由好几家公司共同开发,我们公司做数据仓库部分,包括建立数据仓库和开发之上的数据库仓库管理系统。由于涉及地理信息,需要 GIS 功能,如用户在查看空间数据时,框选经纬度范围,将该空间图层数据导出,并打包下载到本地。本文只讨论导出问题。
开发环境
开发环境如下:
- 客户端:Windows 2003 Server、IE 6+、VS 2005
- 服务器端:Windows 2003 Server、IIS 6、ArcGIS SDE 9.3.2、ArcGIS Server
问题描述
导出的功能虽然实现了,但有次突然导出抛出异常,说证书有问题,无法正常创建 ESRI.ArcGIS.Geodatabase.IFeatureWorkspace 接口。于是,查了相关资料,在导出前后,加入“打开”和“关闭”证书的代码,问题就解决了。
解决方案
定义 BaseLayerData 类
只要在获得 ESRI.ArcGIS.Geodatabase.IFeatureWorkspace 接口的前后,“打开”和“关闭”证书就能行。下面 BaseLayerData 基类,代码如下:
1: using System;
2: using System.Collections.Generic;
3: using System.Text;
4: using System.Configuration;
5:
6: namespace DownLoad.GIS
7: {
8: public class BaseLayerData
9: {
10: #region 私有变量
11: private string _id;
12:
13: private ESRI.ArcGIS.Geodatabase.IFeatureWorkspace _pFeatureWorkspace;
14: private ESRI.ArcGIS.esriSystem.IPropertySet _propertySet ;
15: private ESRI.ArcGIS.esriSystem.IAoInitialize _aoInit;
16:
17: private string _layerTableName;
18: private string _minx;
19: private string _maxy;
20: private string _maxx;
21: private string _miny;
22:
23: private string _filePath;
24: private string _fileNameNonExtension;
25: #endregion
26:
27: #region 公开属性
28: public virtual string Id
29: {
30: get { return this._id; }
31: set { this._id = value; }
32: }
33: public ESRI.ArcGIS.Geodatabase.IFeatureWorkspace PFeatureWorkspace
34: {
35: get
36: {
37: if (this.MyPropertySet != null)
38: {
39: if (this._pFeatureWorkspace == null)
40: {
41: this.OpenLicense();
42:
43: ESRI.ArcGIS.Geodatabase.IWorkspaceFactory pWorkspaceFactory = null;
44: pWorkspaceFactory = new ESRI.ArcGIS.DataSourcesGDB.SdeWorkspaceFactoryClass();
45: ESRI.ArcGIS.Geodatabase.IWorkspace pWorkspace = pWorkspaceFactory.Open(this.MyPropertySet, 0);
46: this._pFeatureWorkspace = pWorkspace as ESRI.ArcGIS.Geodatabase.IFeatureWorkspace;
47:
48: this.CloseLicense();
49: return this._pFeatureWorkspace;
50: }
51: return this._pFeatureWorkspace;
52: }
53: return null;
54: }
55: }
56: protected ESRI.ArcGIS.esriSystem.IPropertySet MyPropertySet
57: {
58: get
59: {
60: if (this._propertySet == null)
61: {
62: this._propertySet = new ESRI.ArcGIS.esriSystem.PropertySetClass();
63: this._propertySet.SetProperty("SERVER", ConfigurationManager.AppSettings["SERVER"]);
64: this._propertySet.SetProperty("INSTANCE", ConfigurationManager.AppSettings["INSTANCE"]);
65: this._propertySet.SetProperty("DATABASE", ConfigurationManager.AppSettings["DATABASE"]);
66: this._propertySet.SetProperty("USER", ConfigurationManager.AppSettings["USER"]);
67: this._propertySet.SetProperty("PASSWORD", ConfigurationManager.AppSettings["PASSWORD"]);
68: this._propertySet.SetProperty("VERSION", ConfigurationManager.AppSettings["VERSION"]);
69: return this._propertySet;
70: }
71: return this._propertySet ;
72: }
73: }
74:
75: protected string LayerTableName
76: {
77: get { return this._layerTableName; }
78: set { this._layerTableName = value; }
79: }
80: protected string Minx
81: {
82: get { return this._minx; }
83: set { this._minx = value; }
84: }
85: protected string Maxy
86: {
87: get { return this._maxy; }
88: set { this._maxy = value; }
89: }
90: protected string Maxx
91: {
92: get { return this._maxx; }
93: set { this._maxx = value; }
94: }
95: protected string Miny
96: {
97: get { return this._miny; }
98: set { this._miny = value; }
99: }
100:
101: /// <summary>
102: /// 文件路径
103: /// </summary>
104: protected string FilePath
105: {
106: get { return this._filePath; }
107: set { this._filePath = value; }
108: }
109: /// <summary>
110: /// 文件名,无扩展名
111: /// </summary>
112: protected string FileNameNonExtension
113: {
114: get { return this._fileNameNonExtension; }
115: set { this._fileNameNonExtension = value; }
116: }
117: #endregion
118:
119: public BaseLayerData()
120: {
121: }
122: public BaseLayerData(string layerTableName,
123: string minx, string maxy, string maxx, string miny,
124: string filePath, string fileNameNonExtension)
125: {
126: this._layerTableName = layerTableName;
127: this._minx = minx;
128: this._maxy = maxy;
129: this._maxx = maxx;
130: this._miny = miny;
131: this._filePath = filePath;
132: this._fileNameNonExtension = fileNameNonExtension;
133:
134:
135: }
136: /// <summary>
137: ///
138: /// </summary>
139: /// <returns></returns>
140: public virtual bool Export()
141: {
142: return false;
143: }
144: /// <summary>
145: /// 创建图层
146: /// </summary>
147: /// <returns></returns>
148: protected ESRI.ArcGIS.Carto.IFeatureLayer CreateLayer()
149: {
150: ESRI.ArcGIS.Carto.IFeatureLayer pFLayer = new ESRI.ArcGIS.Carto.FeatureLayerClass();
151: try
152: {
153: ESRI.ArcGIS.Geodatabase.IFeatureClass pFC = this.PFeatureWorkspace.OpenFeatureClass(this.LayerTableName);
154: pFLayer.FeatureClass = pFC;
155: pFLayer.Name = pFC.AliasName;
156: return pFLayer;
157: }
158: catch
159: {
160: return null;
161: }
162: }
163: /// <summary>
164: /// 创建证书
165: /// </summary>
166: public void OpenLicense()
167: {
168: this._aoInit = null;
169: this._aoInit = new ESRI.ArcGIS.esriSystem.AoInitializeClass();
170: this._aoInit.Initialize(ESRI.ArcGIS.esriSystem.esriLicenseProductCode.esriLicenseProductCodeEngine);
171: }
172: /// <summary>
173: /// 关闭证书
174: /// </summary>
175: public void CloseLicense()
176: {
177: if (this._aoInit != null)
178: {
179: this._aoInit.Shutdown();
180: this._aoInit = null;
181: }
182: }
183: /// <summary>
184: /// 创建导出图层过滤条件
185: /// </summary>
186: /// <param name="minx"></param>
187: /// <param name="maxy"></param>
188: /// <param name="maxx"></param>
189: /// <param name="miny"></param>
190: /// <returns></returns>
191: protected string CreateExpCondition(string minx, string maxy, string maxx, string miny)
192: {
193: string whereClause;
194: int isPass = this.ValidateArea(minx, maxy, maxx, miny);
195: if (isPass == 0)
196: {
197: whereClause = @"sde.st_geometry.st_minx(shape)>" + minx + " and " +
198: " sde.st_geometry.st_maxx(shape)<" + maxx + " and " +
199: " sde.st_geometry.st_miny(shape)>" + miny + " and " +
200: " sde.st_geometry.st_maxy(shape)<" + maxy;
201: }
202: else if (isPass == 1)
203: {
204: whereClause = @"sde.st_geometry.st_minx(shape)>100 and
205: sde.st_geometry.st_maxx(shape)<110 and
206: sde.st_geometry.st_miny(shape)>10 and
207: sde.st_geometry.st_maxy(shape)<20";
208: }
209: else { whereClause = null; }
210: return whereClause;
211: }
212: /// <summary>
213: /// 验证经纬度坐标
214: /// </summary>
215: /// <param name="minx"></param>
216: /// <param name="maxy"></param>
217: /// <param name="maxx"></param>
218: /// <param name="miny"></param>
219: /// <returns>-1为非法;0为合法;1为全是空</returns>
220: private int ValidateArea(string minx, string maxy, string maxx, string miny)
221: {
222: if (minx != null && maxy != null && maxx != null && miny != null)
223: {
224: if (minx.Length == 0 && maxy.Length == 0 && maxx.Length == 0 && miny.Length == 0)
225: {
226: return 1;
227: }
228: else
229: { return 0; }
230: }
231: return -1;
232: }
233: }
234: }
说明:
- BaseLayerData 类是针对图层数据的导出功能;
- 第 41 和 第 48 行为调用“打开”和“关闭”证书方法;
- 第 166~171 行,为“打开”证书方法;第 175~182 行,为“关闭”证书方法。
定义 LayerData 类
该类继承 BaseLayerData,实现按经纬度导出空间图层数据。代码如下:
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Configuration;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.ADF.Connection;
using ESRI.ArcGIS.DataSourcesFile;
namespace DownLoad.GIS
{
/// <summary>
///
/// </summary>
public class LayerData : BaseLayerData
{
public LayerData()
{
}
public LayerData()
{
}
public LayerData(string layerTableName,
string minx, string maxy, string maxx, string miny,
string filePath, string fileNameNonExtension)
: base(layerTableName, minx, maxy, maxx, miny, filePath, fileNameNonExtension)
{
}
public override bool Export()
{
return this.ExportLayer();
}
public bool ExportLayer()
{
ESRI.ArcGIS.Carto.IFeatureLayer pFeatureLayer = this.AddMap();
if (pFeatureLayer != null)
{
ESRI.ArcGIS.Geodatabase.IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;
bool isSuccess = this.ExportLayer(pFeatureClass);
return isSuccess;
}
return false;
}
#region 私有方法
/// <summary>
/// 添加地图
/// </summary>
/// <returns></returns>
private ESRI.ArcGIS.Carto.IFeatureLayer AddMap()
{
ESRI.ArcGIS.Carto.ILayer layer = this.AddLayer();
if (layer != null)
{
ESRI.ArcGIS.Carto.IFeatureLayer featureLayer = layer as ESRI.ArcGIS.Carto.IFeatureLayer;
return featureLayer;
}
return null;
}
/// <summary>
/// 添加图层
/// </summary>
/// <returns></returns>
private ESRI.ArcGIS.Carto.IFeatureLayer AddLayer()
{
ESRI.ArcGIS.Carto.IFeatureLayer pFLayer = new FeatureLayerClass();
ESRI.ArcGIS.Carto.ILayer pLayer = null;
try
{
IFeatureClass pFC = this.PFeatureWorkspace.OpenFeatureClass(this.LayerTableName);
pFLayer.FeatureClass = pFC;
pFLayer.Name = pFC.AliasName;
pLayer = pFLayer as ESRI.ArcGIS.Carto.ILayer;
pLayer.Name = this.LayerTableName;
return pFLayer;
}
catch
{
return null;
}
}
/// <summary>
/// 导出图层文件SHP格式
/// </summary>
/// <returns></returns>
private bool ExportLayer(ESRI.ArcGIS.Geodatabase.IFeatureClass apFeatureClass)
{
string whereClause = this.CreateExpCondition(this.Minx, this.Maxy, this.Maxx, this.Miny);
if (apFeatureClass != null && whereClause != null)
{
this.OpenLicense();
//设置导出要素类的参数
ESRI.ArcGIS.Geodatabase.IDataset pOutDataset = (ESRI.ArcGIS.Geodatabase.IDataset)apFeatureClass;
ESRI.ArcGIS.Geodatabase.IFeatureClassName myFeatureClassName = (IFeatureClassName)pOutDataset.FullName;
//创建一个输出shp文件的工作空间
ESRI.ArcGIS.Geodatabase.IWorkspaceFactory myShpWorkspaceFac = new ShapefileWorkspaceFactoryClass();
ESRI.ArcGIS.Geodatabase.IWorkspaceName myWorkspaceName = myShpWorkspaceFac.Create(this.FilePath, this.FileNameNonExtension, null, 0);
//创建一个要素集合和类
ESRI.ArcGIS.Geodatabase.IFeatureClassName pInFeatureClassName = new FeatureClassNameClass();
ESRI.ArcGIS.Geodatabase.IDatasetName pInDatasetClassName = null;
pInDatasetClassName = (IDatasetName)pInFeatureClassName;
pInDatasetClassName.Name = this.FileNameNonExtension;
pInDatasetClassName.WorkspaceName = myWorkspaceName;
ESRI.ArcGIS.Geodatabase.IQueryFilter myQueryFilter = new QueryFilterClass();
myQueryFilter.WhereClause = whereClause;
ESRI.ArcGIS.Geodatabase.IFields myFields = null; // 所有字段
ESRI.ArcGIS.Geodatabase.IEnumFieldError pEnumFieldError = null;
ESRI.ArcGIS.Geodatabase.IFields pInFields = apFeatureClass.Fields;
ESRI.ArcGIS.Geodatabase.IFieldChecker pFieldChecker = new ESRI.ArcGIS.Geodatabase.FieldChecker();
pFieldChecker.Validate(pInFields, out pEnumFieldError, out myFields);
//查找几何字段,获得几何定义,并设置空间参考和网格
ESRI.ArcGIS.Geodatabase.IField pGeoField = null; // 几何字段
for (long iCounter = 0; iCounter < myFields.FieldCount; iCounter++)
{
if (myFields.get_Field((int)iCounter).Type == esriFieldType.esriFieldTypeGeometry)
{
pGeoField = myFields.get_Field((int)iCounter);
break;
}
}
ESRI.ArcGIS.Geodatabase.IGeometryDef myGeometryDef = pGeoField.GeometryDef;
try
{
ESRI.ArcGIS.Geodatabase.IFeatureDataConverter myFeatureDataConverter = new FeatureDataConverterClass();
myFeatureDataConverter.ConvertFeatureClass(myFeatureClassName,
myQueryFilter,
null,
pInFeatureClassName,
myGeometryDef,
myFields,
"", 1000, 0);
this.CloseLicense();
return true;
}
catch
{
this.CloseLicense();
return false;
}
}
return false;
}
#endregion
}
}