最近在做一个房籍图的管理系统,其中需要处理一下地图数据。要求是给图幅接合表的图层增加一个字段,然后在属性数据库中查询每个要素(格网)的图幅数,将结果写入新建字段里。
对于经常用程序做GIS数据处理的,这个实现起来并不难,使用ArcEngine简单写个处理程序即可。不过,不同于之前的应用类程序,这种数据处理程序是要考虑效率问题的。
我第一次写的函数
private void FJT_Click(object sender, EventArgs e)
{
Stopwatch sp1 = new Stopwatch();
string sql="";
IFeatureClass icladd = AEDataHelper.OpenMdbFeatureClass("D:\\数据\\最新汇总.mdb", "WBgrid");
IFeatureCursor ifcu = icladd.Update(null, false);
IFeature pfea = ifcu.NextFeature();
sqlConnection.Open();
while (pfea!=null)
{
int xh = pfea.Fields.FindField("testname");
string va = pfea.get_Value(xh).ToString();
sql = "SELECT count(*) as cou from tm_nameinfo where name=\'" + va+"\'";
DataTable dt = Executmdbsql(sql,sqlConnection);
// DataTable dt = Executmdbsql2(sql);
string guiddd = dt.Rows[0]["cou"].ToString();
int fjt = pfea.Fields.FindField("FJTcount");
pfea.set_Value(fjt, guiddd);
pfea.Store();
pfea = ifcu.NextFeature();
}
sqlConnection.Close();
sqlConnection.Dispose();
sp1.Stop();
MessageBox.Show("处理完成!!!!!" + "耗时:" + sp1.ElapsedMilliseconds.ToString()+"毫秒");
}
19272条要素,所需时间为107秒。速度怎么说呢,不好说,因为没有对比。如果想提速,可以从这几个方面考虑。
1 这函数里有循环,把能放在循环外的放外面
2 sql查询速度应该很快,可以忽略
3 虽然我是在更新空间要素,但是我更新的是它的属性字段,是否可以换个写法
4 ArcEngine 中有好多接口,不同接口的执行效率可能不同。
然后依据4我又换了一种写法
private void FJT_Click(object sender, EventArgs e)
{
sp1.Start();
string sql="";
IFeatureClass icladd = AEDataHelper.OpenMdbFeatureClass("D:\\数据\\最新汇总.mdb", "WBgrid");
IFeatureCursor ifcu = icladd.Update(null, false);
IFeature pfea = ifcu.NextFeature();
sqlConnection.Open();
while (pfea!=null)
{
int xh = pfea.Fields.FindField("testname");
string va = pfea.get_Value(xh).ToString();
sql = "SELECT count(*) as cou from tm_nameinfo where name=\'" + va+"\'";
DataTable dt = Executmdbsql(sql,sqlConnection);
// DataTable dt = Executmdbsql2(sql);
string guiddd = dt.Rows[0]["cou"].ToString();
int fjt = pfea.Fields.FindField("FJTcount");
pfea.set_Value(fjt, guiddd);
ifcu.UpdateFeature(pfea);
// pfea.Store();使用update效率会比store()好的多
pfea = ifcu.NextFeature();
}
sqlConnection.Close();
sqlConnection.Dispose();
sp1.Stop();
MessageBox.Show("处理完成!!!!!" + "耗时:" + sp1.ElapsedMilliseconds.ToString()+"毫秒");
}
这次执行时间为52秒,只是改动一个地方,把pfea.Store()改为使用游标的ifcu.UpdateFeature(pfea)。从理论上看,前者相当于把要素的所有属性重新存了进来,而后者只是把更新的属性写入,自然后者效率高些。然而这并没完,根据3
我又换了一种写法
private void FJTtest_Click(object sender, EventArgs e)
{
Stopwatch sp1 = new Stopwatch();
string sql = "";
ITable it1 = AEDataHelper.OpenMdbTable("D:\\数据\\最新汇总.mdb", "WBgrid");
ICursor ic1 = it1.Update(null, false);
IRow prow = ic1.NextRow();
sqlConnection.Open();
while(prow!=null)
{
string xh = prow.get_Value(35).ToString();
sql = "SELECT count(*) as cou from tm_nameinfo where name=\'" + xh + "\'";
DataTable dt = Executmdbsql(sql, sqlConnection);
string guiddd = dt.Rows[0]["cou"].ToString();
prow.set_Value(34, guiddd);
ic1.UpdateRow(prow);
prow = ic1.NextRow();
}
sqlConnection.Close();
sqlConnection.Dispose();
sp1.Stop();
MessageBox.Show("处理完成!!!!!" + "耗时:" + sp1.ElapsedMilliseconds.ToString() + "毫秒");
}
这次执行完,速度是47秒!!!
细心的人可以发现,这次差别只是一个使用的是FeatureClass(即空间要素集),一次使用的是ITable(属性表)。难道这效率差是操作空间要素和属性要素造成的?理论上,我又没动空间数据,怎么可能又效率差?我又想了想,把第二种写法改了一下
private void FJT_Click(object sender, EventArgs e)
{
sp1.Start();
string sql="";
IFeatureClass icladd = AEDataHelper.OpenMdbFeatureClass("D:\\数据\\最新汇总.mdb", "WBgrid");
IFeatureCursor ifcu = icladd.Update(null, false);
IFeature pfea = ifcu.NextFeature();
sqlConnection.Open();
while (pfea!=null)
{
string va = pfea.get_Value(35).ToString();
sql = "SELECT count(*) as cou from tm_nameinfo where name=\'" + va+"\'";
DataTable dt = Executmdbsql(sql,sqlConnection);
string guiddd = dt.Rows[0]["cou"].ToString();
pfea.set_Value(34, guiddd);
ifcu.UpdateFeature(pfea);
// pfea.Store();使用update效率会比store()好的多
pfea = ifcu.NextFeature();
}
sqlConnection.Close();
sqlConnection.Dispose();
sp1.Stop();
MessageBox.Show("处理完成!!!!!" + "耗时:" + sp1.ElapsedMilliseconds.ToString()+"毫秒");
}
这次。。。46秒,和第三种写法差不多了。原来,执行效率和操作空间数据和属性数据没关系。。。
总结:ArcEngine 更新数据,使用游标更新要比使用要素直接更新快。。。。写了这么多,就得出个这么一句话。