第十二节 实例七-让Micaps直接连接数据库显示数据
上一节我们已能让Micaps支持新数据类型,但目前大量数据在数据库中保存,是否能让Micaps直接读取数据库中的数据显示呢?这一节我们将做一个Micaps直连数据库显示数据的插件。
Micaps实际上已经预留了数据库、XML数据读取接口,但它并没有实现。其实完全没必要将数据库与文件接口分开,主程序只用让插件绘图,其它的都让插件自己处理,不管数据是来自文件、数据库还是网络。
要实现这个功能,需解决如下问题:
- 数据库数据启动问题。普通文件我们可以直接打开文件显示,也可以做出成综合图,数据库没有文件,怎么启动呢?第一种方法,按HelloWorld例子的方法,给Micaps主菜单添加一个按钮,单击按钮后,创建数据库图层并显示;第二种方法,建一个特定文件名文件,如sxaws.udl,文件内容可以随意(但最好把它当作数据库配置文件,保存数据库连接串等,如sxaws.udl),然后按上节的例子,打开sxaws.udl的文件时,连接数据库显示数据,这样可以就可以把它加进数据检索菜单或者综合图。本节将使用第二种方法。
- 连接数据库读取数据问题。当用户打开文件时(如sxaws.udl),在CreateLayerForFile(OpenedFile file)函数中编写处理代码,其中file参数仅仅作为一个标识或配置文件,代码中直接创建数据库图层就可以了。
1、Addin文件
与上节一样,增加一个显示绑定段,类名为:SxAwsDataBindings。
<Path name="/Workspace/DisplayBindings"> <DisplayBinding id="SxAwsdb" type="Layer" class="SxAwsDataBindings"/> </Path>
2、代码
实现SxAwsDataBindings类,代码除了对文件名的判断不同,其它与上节都一样:
public bool CanCreateForFile(string filename) { //仅能打开名为"sxaws.udl"的文件 string fn = Path.GetFileName(filename).ToLower(); return fn == "sxaws.udl"; }
再实现数据读取,在CreateLayerForFile(OpenedFile file)中编写数据读取代码。与上节唯一不同的是,这里创建的是一个叫做SxAws的图层类。
public ILayer CreateLayerForFile(OpenedFile file) { //取得当前视图,转换为Micaps地图视图 var mainRenderView = WorkspaceSingleton.Workspace.ActiveViewContent as IMicapsMainView; //如果当前视图是地图,则加载图层 if (mainRenderView != null) { //创建自动站数据库图层 SxAws Chart = new SxAws(); //用它创建Micaps图层绑定对象 MicapsDataLayerWrapper layer = new MicapsDataLayerWrapper(Chart); //给图层的地图对象赋值 Chart.Map = mainRenderView.Map; //加载数据 layer.Load(file, file.OpenRead()); file.CloseIfAllViewsClosed(); layer.LayerName = Chart.Description(); return layer; } return null; }
SxAws类继承了C_ChartBase类,重写了 ReadFile(string filename)和Draw(GLGraphics g)虚函数,分别实现数据读取和绘图工作。与上节不同的是,读取数据库时,我们不是从sxaws.udl文件中读取数据,而是从sxaws.udl中读取数据库连接串,然后连接数据库读取数据。实际开发中,可根据需要修改读数据库和绘图代码,这里我读的陕西省的数据库的,把代码的直接贴上去是运行不了的。
public class SxAws : C_ChartBase { public override void Draw(GLGraphics g) { float x, y; float ang; foreach (DataRow row in _AwsData.Tables[0].Rows) { string t = row["dewtemp"].ToString(); float lat = float.Parse(row["latitude"].ToString()); float lon = float.Parse(row["longitude"].ToString()); Map.MemTY(lon, lat, out x, out y); g.ShowNumber(t, x, y, 1, 1, Color.Red); float dd = 9999; float ff = 9999; float.TryParse(row["WindDirect"].ToString(), out dd); float.TryParse(row["WindVelocity"].ToString(),out ff); if(dd!=9999&& ff !=9999) { ang = dd;//= ang - 270; ang = ang + 180; if (ang >= 360) ang = ang - 360.0f; ang = ang * 0.0174532925F;//转化为弧度 g.ShowWind(ff/10.0f, x, y, 0.8f, 0.8f, Color.Black, 360f - ang * 180.0f / (float)Math.PI, true); } } } private DataSet _AwsData = new DataSet(); public override string ReadFile(string filename) { string conString = @"Data Source=172.23.64.146;Persist Security Info=True;User ID=aws;;Initial Catalog=elementinfo"; SqlConnection connection = new SqlConnection(conString); string sql = @"SELECT * FROM dbo.tabTimeData INNER JOIN dbo.tabStation ON dbo.tabTimeData.StationNum = dbo.tabStation.StationNum WHERE (ObservTimes = '2013010101')"; SqlDataAdapter adapter = new SqlDataAdapter(sql, connection); _AwsData.Clear(); adapter.Fill(_AwsData); connection.Close(); return "Success"; } ………………… ………………… ………………… }
可惜的是,直接读取数据库时,Micaps的翻页功能无法使用。Micaps的图层类虽然预留了前一时次、后一时次的抽象方法,但却在翻页代码中却没有调用它,而是直接搜索文件来实现。我们调用数据库没有文件,就造成在插件代码中无法控制翻页。解决办法是我们重新编写翻页插件替换Micaps自带的翻页功能,翻页时,先调用每个图层的翻页方法,如果发生异常,再执行文件方式翻页(此方法并不安全,其它插件的翻页代码如果未抛出异常,那它的文件方式翻页功能将实效)。
下图即直接连接陕西省局自动站数据库绘图的效果: