Infobright 统计查看器 - MVVM





5.00/5 (2投票s)
WPF 应用程序,用于生成和显示 Infobright 大数据统计信息。
引言
此 .NET WPF 应用程序连接到 Infobright 数据仓库数据库,并显示压缩统计信息以及其他有用的信息。 该代码遵循 MVVM 设计模式。
它看起来是这样的
连接成功后,将显示主窗口。
表统计信息位于左侧。 列统计信息位于右侧。 您可以使用下拉菜单更改数据库。
所需软件
- Visual Studio 2010
- .NET Framework 4
- MySQL 的 ADO.NET 驱动程序
为了在 Visual Studio 中运行该程序,您必须下载并安装 ADO.NET 驱动程序。 安装完成后,您必须添加对 MySql.Data 的项目引用。 现在您应该能够构建和执行该程序。
视图的图表
在下面,您将看到程序树以及视图及其相应视图模型的图表。
您可能会注意到未显示 ConnectDialog
视图。 DatabaseConnectionViewModel
对应于此视图。
源代码
有很多代码,因此我将尝试专注于更有趣和/或令人困惑的部分。
BrighthouseStatistics.xaml.cs
这是程序启动时的主要逻辑。 加载控件后,将创建一个新的 ConnectDialog
窗口。 如果连接成功,MySQL 连接将传递到我们的视图模型,并将焦点转移到主窗口。
public partial class BrighthouseStatistics : UserControl
{
private BrighthouseStatisticsViewModel _viewModel = null;
public MySqlConnection MySqlConnection { get; set; }
public BrighthouseStatistics()
{
InitializeComponent();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (DesignerProperties.GetIsInDesignMode(this))
{
return;
}
else
{
this.IsEnabled = false;
Window dialog = new ConnectDialog();
dialog.Owner = Window.GetWindow(this);
if (dialog.ShowDialog() == true)
{
DatabaseConnectionViewModel databaseConnectionViewModel =
(DatabaseConnectionViewModel)dialog.DataContext;
MySqlConnection = databaseConnectionViewModel.MySqlConnection;
_viewModel = new BrighthouseStatisticsViewModel(MySqlConnection);
this.DataContext = _viewModel;
IsEnabled = true;
}
else
{
Application.Current.Shutdown();
}
}
}
}
ConnectDialog.xaml
如您在上面所见,ConnectDialog
窗口有四个文本框,用户可以在其中输入登录信息。 只有当文本框没有验证错误时,窗口底部的“连接”按钮才可见。 您可以在下面的 XAML 中看到如何完成此操作。 稍后,您将看到如何在视图模型中实现验证。
<Button IsDefault="True" Content="Connect" Height="23" HorizontalAlignment="Right" Margin="0,0,8,8"
Name="btnTestConnection" VerticalAlignment="Bottom" Width="80" Click="btnConnect_Click">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="false" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=tbHost, Path=(Validation.HasError)}"
Value="false" />
<Condition Binding="{Binding ElementName=tbUser, Path=(Validation.HasError)}"
Value="false" />
<Condition Binding="{Binding ElementName=pbPassword, Path=(Validation.HasError)}"
Value="false" />
<Condition Binding="{Binding ElementName=tbPort, Path=(Validation.HasError)}"
Value="false" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="true" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
ConnectDialog.xaml.cs
单击“连接”按钮后,将调用 btnConnect_Click
。 此函数在 DatabaseConnection
ViewModel
中执行连接命令。 如果连接成功,
ConnectDialog
窗口将关闭。 如果连接不成功,则 MessageBox
将显示详细的错误消息。
private void btnConnect_Click(object sender, RoutedEventArgs e)
{
_viewModel.Connect(null);
if (_viewModel.IsConnected)
{
DialogResult = true;
this.Close();
}
else
{
MessageBox.Show(this, _viewModel.ConnectionError, "Connection Error");
}
}
DatabaseConnectionViewModel.cs
此辅助函数确定连接是否成功。 请注意,我们从 Database
类中的函数获取实际连接(稍后我将讨论这个类)。 此函数的参数是 DatabaseConnectionViewModel
的成员变量,这些变量绑定到 ConnectDialog
窗口中的文本框。
private void ConnectHelper()
{
MySqlConnection sqlConnection = Database.GetSqlConnection(Host, User, Password, Port);
try
{
sqlConnection.Open();
if (sqlConnection.State == ConnectionState.Open)
{
if (IsBrighthouse(sqlConnection))
{
MySqlConnection = sqlConnection;
IsConnected = true;
}
else
{
ConnectionError = "Failure! This is not an Infobright database.";
MySqlConnection = null;
IsConnected = false;
}
}
else
{
ConnectionError = "Failure! The database connection could not be opened.";
MySqlConnection = null;
IsConnected = false;
}
}
catch (MySqlException mySqlException)
{
ConnectionError = "Failure! " + mySqlException.Message;
MySqlConnection = null;
IsConnected = false;
}
}
登录信息的验证也在此类中使用 IDataErrorInfo
接口完成。
#region IDataErrorInfo Members
public string Error
{
get { throw new NotImplementedException(); }
}
public string this[string columnName]
{
get
{
string result = null;
if (columnName == "Host")
{
if (string.IsNullOrEmpty(Host))
result = "Please enter a host address.";
}
if (columnName == "User")
{
if (string.IsNullOrEmpty(User))
result = "Please enter a user name.";
}
if (columnName == "Port")
{
if (Port < 0 || Port > 65535)
result = "Please enter a valid port number.";
}
return result;
}
}
#endregion
Database.cs
Database
类包含多个与数据库交互并生成统计信息的关键函数。
这个简单的函数使用登录信息来创建 MySqlConnection。
public static MySqlConnection GetSqlConnection(string host, string user, string password, int port)
{
string connectionString = "server=" + host + ";user=" + user +
";password=" + password + ";port=" + port + ";";
MySqlConnection sqlConnection = new MySqlConnection(connectionString);
return sqlConnection;
}
此函数获取 Infobright 数据库名称并将它们返回到列表中。 请注意,未使用“SHOW DATABASES”查询。 相反,我们使用一个只包含 Infobright 数据库名称的查询。
public static IList<String> GetDatabases(MySqlConnection mySqlConnection)
{
string query = "SELECT table_schema FROM information_schema.TABLES WHERE ENGINE =
'BRIGHTHOUSE' GROUP BY table_schema";
IList<String> dbNames = new List<String>();
MySqlCommand command = new MySqlCommand(query, mySqlConnection);
MySqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
string dbName = reader.GetString(0);
dbNames.Add(dbName);
}
reader.Close();
return dbNames;
}
在这里,我们有一个更复杂的函数,它获取特定数据库的表统计信息,并将它们以列表的列表形式返回。 压缩存储在表注释中,因此使用辅助函数来解析该值。
public static IList<IList<String>> GetBrighthouseTables(MySqlConnection mySqlConnection)
{
string query = "SHOW TABLE STATUS WHERE ENGINE='BRIGHTHOUSE'";
IList<IList<String>> tableData = new List<IList<String>>();
MySqlCommand command = new MySqlCommand(query, mySqlConnection);
MySqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
string tableName = reader.GetString(0);
string comment = reader.GetString(17);
string compression = GetCompressionFromTableComment(comment);
string compressedSize = (double.Parse(reader.GetString(6)) / 1048576.0).ToString();
IList<String> tableStats = new List<String>();
tableStats.Add(tableName);
tableStats.Add(compression);
tableStats.Add(compressedSize);
tableData.Add(tableStats);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
reader.Close();
return tableData;
}
这可能是 Database
类中最复杂的函数。 它计算给定表的列统计信息,并将它们以列表的列表形式返回。 请注意,当调用 GetCount
辅助函数时,会克隆连接。 这是因为 GetCount
执行另一个查询,并且不能在同一个连接上打开两个 MySqlDataReaders
。 此代码的另一个重要部分是异常处理。 发生 MySqlException
时,有时可以关闭连接。 为了防止程序中出现其他错误,将重新打开连接并重置当前数据库。
public static IList<IList<String>> GetColumns(string tableName, MySqlConnection mySqlConnection)
{
string query = "SHOW FULL COLUMNS FROM " + tableName;
IList<IList<String>> columns = new List<IList<String>>();
string currentDatabase = GetCurrentDatabase(mySqlConnection);
MySqlCommand command = new MySqlCommand(query, mySqlConnection);
MySqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
IList<String> column = new List<String>();
string columnName = reader.GetString(0);
column.Add(columnName);
string columnType = reader.GetString(1);
column.Add(columnType);
string columnComment = reader.GetString(8);
string compression = GetCompressionFromColumnComment(columnComment);
column.Add(compression);
string count = GetCount(mySqlConnection.Clone(), currentDatabase, tableName, columnName);
column.Add(count);
columns.Add(column);
}
}
catch (MySqlException ex)
{
MessageBox.Show("An error occured: " + ex.Message);
if (mySqlConnection.State != ConnectionState.Open)
{
mySqlConnection.Open();
if (currentDatabase != null)
{
UseDatabase(currentDatabase, mySqlConnection);
}
}
}
reader.Close();
return columns;
}
代码摘要
使用 Database 类中的函数,各种视图模型使用简单的 CollectionView
或 ListCollectionView
绑定来在页面上显示数据。 如果您对任何代码有任何问题或意见,请告诉我。