Working with ADO.NET Schema APIs

本文介绍如何利用ADO.NET的GetSchema方法从数据库中检索模式信息,并通过一个简单的数据库资源管理器实例演示了如何根据不同的元数据集合过滤并展示数据库中的表、视图及存储过程等。

Introduction

In majority of data driven applications developers deal with SQL queries that select, insert, update or delete data from the database. However, at times you need to retrieve schema information from the database. Suppose you are building applications that performs data import and export between two or more databases. As a good solution you would want to retrieve table schema at runtime rather than hard coding it. Luckily, ADO.NET provides a set of classes that allow you to query database schema. In this article I will illustrate how these classes work.

Possible Approaches

Whenever you wish to retrieve database schema you can use couple of techniques:

  • Store database schema information in some XML file and then read this XML file in your application.
  • Use system stored procedures of the underlying database to retrieve schema information.

As you might have guessed, the first technique is not so good as generating XML file is a manual operation. Even the second approach has its own drawbacks. All databases do not have the same set of stored procedures for retrieving database schema. Further it is not guaranteed that these stored procedures will return information in consistent manner. Considering these limitations it is worth investigating ADO.NET schema API model.

Retrieving Database Schema

In order to retrieve database schema information ADO.NET connection object provides GetSchema() method. The GetSchema() method comes in three flavors:

  • GetSchema() method called without any parameters returns you what is known as metadata collections. A metadata collection is a collection that gives metadata information about a specific type of item (table, view, stored procedure etc.)
  • GetSchema() method called by passing a metadata collection name returns information about items found in the specified collection. For example, if you specify tables metadata collection then GetSchema() method will return information about all the tables in the database. The information is returned as a DataTable.
  • GetSchema() method called by passing metadata collection name and filter criteria returns the items from the collection after applying the filter criteria.

Metadata Collections

Metadata collections are collections that contain information about items whose schema can be retrieved. The common metadata collections are:

  • Tables : Gives information about tables belonging to a database
  • Views : Gives information about views belonging to a database
  • Columns : Gives information about table columns
  • ViewColumns : Gives information about columns of views
  • Procedures : Gives information about stored procedures
  • ProcedureParameters : Gives information about stored procedure parameters
  • Indexes : Gives information about indexes
  • IndexColumns : Gives information about columns of the indexes
  • DataTypes : Gives information about data types
  • Users : Gives information about database users

Restrictions

Metadata collections by default return the whole information about an item. For example, ProcedureParameters collection returns information about all the parameters of all the stored procedures in the system. Many times this is not what you want. You want parameter information of a specific stored procedure. Such filtering of metadata collection can be achieved via restrictions. A restriction is a string array that specifies the filter criteria. Not all the metadata collections share the same filter criteria. A particular metadata collection has fixed criterion on which it can be filtered. For example, the tables metadata collection can be filtered on the basis of catalog name, owner name and table name. The other metadata collections may have additional (or less) filter criterions.

Creating a Simple Database Explorer

In order to illustrate what we just discussed, lets create a simple database explorer as shown below: 

The database explorer simply allows you to display databases, tables, views and stored procedures in a tree fashion.

To begin with, create a new Windows Forms application in Visual Studio and drag and drop a TreeView on it. You will need a helper method that you can call from multiple places to quickly add a node to the TreeView. This helper method is shown below:

private TreeNode AddNode(TreeNode parent,

string text,string tag,int imgIndex)

{

TreeNode child = new TreeNode(text);

child.ImageIndex = imgIndex;

child.SelectedImageIndex = imgIndex;

child.Tag = tag;

if (parent != null)

{

parent.Nodes.Add(child);

}

else

{

treeView1.Nodes.Add(child);

}

return child;

}

The AddNode() helper method accepts parent node, text to be displayed for the newly added node, a unique tag for the new node so that you can identify that node later and image index indicating the icon of the node. Inside it creates a new TreeNode and sets its various properties. If the parent node is null the new node is added directly to the tree view otherwise it gets appended as a child node of the parent node.

You need one more helper method named GetSchemaInfo() that returns schema information about a specific item. The GetSchemaInfo() method is shown below:

private DataTable GetSchemaInfo

(SchemaCollection collection,string entity)

{

DataTable dt = null;

string collectionname = "";

string[] restrictions = null;

 

switch (collection)

{

case SchemaCollection.Databases:

collectionname = "Databases";

if (entity != "")

{

restrictions = new string[1];

restrictions[0] = entity;

}

break;

case SchemaCollection.Tables:

collectionname = "Tables";

if (entity != "")

{

restrictions = new string[4];

restrictions[0] = entity;

}

break;

case SchemaCollection.Views:

collectionname = "Views";

if (entity != "")

{

restrictions = new string[3];

restrictions[0] = entity;

}

break;

case SchemaCollection.Columns:

collectionname = "Columns";

if (entity != "")

{

restrictions = new string[4];

restrictions[2] = entity;

}

break;

case SchemaCollection.ViewColumns:

collectionname = "ViewColumns";

if (entity != "")

{

restrictions = new string[4];

restrictions[2] = entity;

}

break;

case SchemaCollection.StoredProcedures:

collectionname = "Procedures";

if (entity != "")

{

restrictions = new string[4];

restrictions[0] = entity;

}

break;

case SchemaCollection.Parameters:

collectionname = "ProcedureParameters";

if (entity != "")

{

restrictions = new string[4];

restrictions[2] = entity;

}

break;

}

string strConn = ConfigurationManager.

ConnectionStrings["connstr"].ConnectionString;

SqlConnection cnn = new SqlConnection(strConn);

cnn.Open();

dt = cnn.GetSchema(collectionname,restrictions);

cnn.Close();

return dt;

}

The GetSchemaInfo() method accepts two parameters viz. a value from SchemaCollection enumeration and name of the collection. The SchemaCollection enumeration is user defined enumeration and looks as shown below:

public enum SchemaCollection

{

Databases,

Tables,

Views,

StoredProcedures,

Columns,

ViewColumns,

Parameters

}

The SchemaCollection enumeration simply indicates the metadata collection to be used for retrieving schema information.

Depending on the collection name the applicable restrictions vary. For example, if you are using databases collection then the restrictions array should contain just one element indicating the database name whose schema is to be retrieved. On the other hand if you are using tables collection then the restrictions array contains four elements for specifying catalog name, owner name, table name and table type respectively. The same applies for Views, Columns, ViewColumns, Procedures and ProcedureParameters collections. Then the code retrieves the database connection string from the application configuration file. An instance of SqlConnection object is then created and opened. The GetSchema() method is called on the connection by passing the collection name and restriction array. The DataTable thus obtained is returned back to the caller.

As the form loads you need to retrieve information about all the databases and display database names in the tree view. This is done in the Lod event of the form as shown below:

private void Form2_Load(object sender,

EventArgs e)

{

TreeNode root= treeView1.Nodes.Add("All Databases");

DataTable db = GetSchemaInfo

(SchemaCollection.Databases, "");

foreach (DataRow row in db.Rows)

{

AddNode(root, row["DATABASE_NAME"].ToString(),

"Database",0);

}

}

Here, the code adds a toot node with text "All Databases". It then calls GetSchemaInfo() method specifying that we want to retrieve information about databases. The returned DataTable contains rows depending on the databases available. Each row contains many columns. We use DATABASE_NAME column to display database name. Notice that while adding the node the tag of the node is set to "Database". This way we can identify whether ta node represents database or any other type of item.

When user selects a particular node we need to populate its child nodes. For example, if a node represents a database clicking on it should populate tables, views and procedures within it. If a node is a table clicking on it should populate its column information and so on. This task is accomplished in the NodeMouseClick event handler of the TreeView control.

private void treeView1_NodeMouseClick

(object sender, TreeNodeMouseClickEventArgs e)

{

DataTable dt = null;

if (e.Node.Tag != null)

{

e.Node.Nodes.Clear();

switch (e.Node.Tag.ToString())

{

case "Database":

TreeNode tblfolder=AddNode(e.Node,

 "Tables", null, 5);

tblfolder.SelectedImageIndex = 6;

TreeNode viewfolder = AddNode(e.Node,

 "Views", null, 5);

viewfolder.SelectedImageIndex = 6;

TreeNode procfolder = AddNode(e.Node,

 "Procedures", null, 5);

procfolder.SelectedImageIndex = 6;

dt = GetSchemaInfo(SchemaCollection.Tables,

e.Node.Text);

foreach (DataRow row in dt.Rows)

{

AddNode(tblfolder, row["TABLE_NAME"].ToString(),

"Table",1);

}

dt = GetSchemaInfo(SchemaCollection.StoredProcedures,

e.Node.Text);

foreach (DataRow row in dt.Rows)

{

AddNode(procfolder, row["SPECIFIC_NAME"].ToString(),

"Procedure",2);

}

dt = GetSchemaInfo(SchemaCollection.Views, e.Node.Text);

foreach (DataRow row in dt.Rows)

{

AddNode(viewfolder, row["TABLE_NAME"].ToString(),

 "View", 1);

}

break;

case "Table":

dt = GetSchemaInfo(SchemaCollection.Columns,

e.Node.Text);

foreach (DataRow row in dt.Rows)

{

AddNode(e.Node, row["COLUMN_NAME"].ToString() +

" (" + row["DATA_TYPE"].ToString() + "," +

(row["IS_NULLABLE"].ToString() == "YES" ? "NULL" :

"NOT NULL") + ")", "Column", 3);

}

break;

case "View":

dt = GetSchemaInfo(SchemaCollection.ViewColumns,

e.Node.Text);

foreach (DataRow row in dt.Rows)

{

AddNode(e.Node, row["COLUMN_NAME"].ToString(),

"ViewColumn", 3);

}

break;

case "Procedure":

dt = GetSchemaInfo(SchemaCollection.Parameters,

e.Node.Text);

foreach (DataRow row in dt.Rows)

{

AddNode(e.Node, row["PARAMETER_NAME"].ToString() +

" (" + row["DATA_TYPE"].ToString() + ")",

"Parameter", 4);

}

break;

}

}

}

The code above calls the same GetSchemaInfo() helper method depending on the Tag property of the tree node being clicked. If the Tag is "Database" then information about tables, views and stored procedures is fetched and their list is populated. Notice the DataTable column names used in the for loop. Table name, stored procedure name and view name is obtained from TABLE_NAME, SPECIFIC_NAME and TABLE_NAME columns respectively.

The other cases perform similar work Tag values of "Table", "View" and "Procedure". The column name, data type and NULL behavior is retrieved from COLUMN_NAME, DATA_TYPE and IS_NULLABLE columns. Similarly, parameter name and its data type is retrieved from PARAMETER_NAME and DATA_TYPE columns respectively.

Before you run the application do not forget to add the database connection string in the application configuration file as shown below:

<connectionStrings>

<add

name="connstr"

connectionString="data source=./sqlexpress;

initial catalog=northwind;

integrated security=true"

providerName="System.Data.SqlClient"/>

</connectionStrings>

</configuration>

That's it! You can now run the application and try navigating different database objects.

 Download Source Code

原文地址:http://www.dotnetbips.com/articles/bcd9065e-94af-4063-8360-f916571f9872.aspx

(Kriging_NSGA2)克里金模型结合多目标遗传算法求最优因变量及对应的最佳自变量组合研究(Matlab代码实现)内容概要:本文介绍了克里金模型(Kriging)与多目标遗传算法NSGA-II相结合的方法,用于求解最优因变量及其对应的最佳自变量组合,并提供了完整的Matlab代码实现。该方法首先利用克里金模型构建高精度的代理模型,逼近复杂的非线性系统响应,减少计算成本;随后结合NSGA-II算法进行多目标优化,搜索帕累托前沿解集,从而获得多个最优折衷方案。文中详细阐述了代理模型构建、算法集成流程及参数设置,适用于工程设计、参数反演等复杂优化问题。此外,文档还展示了该方法在SCI一区论文中的复现应用,体现了其科学性与实用性。; 适合人群:具备一定Matlab编程基础,熟悉优化算法和数值建模的研究生、科研人员及工程技术人员,尤其适合从事仿真优化、实验设计、代理模型研究的相关领域工作者。; 使用场景及目标:①解决高计算成本的多目标优化问题,通过代理模型降低仿真次数;②在无法解析求导或函数高度非线性的情况下寻找最优变量组合;③复现SCI高水平论文中的优化方法,提升科研可信度与效率;④应用于工程设计、能源系统调度、智能制造等需参数优化的实际场景。; 阅读建议:建议读者结合提供的Matlab代码逐段理解算法实现过程,重点关注克里金模型的构建步骤与NSGA-II的集成方式,建议自行调整测试函数或实际案例验证算法性能,并配合YALMIP等工具包扩展优化求解能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值