65.9K
CodeProject 正在变化。 阅读更多。
Home

Infobright 统计查看器 - MVVM

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2012 年 6 月 12 日

MIT

3分钟阅读

viewsIcon

25515

downloadIcon

466

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。 此函数在 DatabaseConnectionViewModel 中执行连接命令。 如果连接成功,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 类中的函数,各种视图模型使用简单的 CollectionViewListCollectionView 绑定来在页面上显示数据。 如果您对任何代码有任何问题或意见,请告诉我。

© . All rights reserved.