切换 SQLite 数据库文件始终在 datagridview C# Winforms 中显示旧 SQLite 数据库文件中的数据

问题描述 投票:0回答:1

我正在开发一个处理多用户和多公司概念的 Winforms 应用程序。如果用户进入公司并打开某些内容(例如帐户),它会在 datagridview 中显示该数据,但是当用户在应用程序内切换公司时,它也会切换 SQLite 数据库文件。

但问题是:datagridview 没有显示第二家公司的数据,它仍然显示第一家公司的数据。

这是我的代码:

private void ViewSearch(string search)
{
     try
     {
         string query = string.Empty;

         if (string.IsNullOrEmpty(search) && !string.IsNullOrEmpty(search))
         {
             query = "Select * from tblAccount";
         }
         else
         {
             query = "Select * from tblAccount where AccountName Like '%" + search + "%'";
             ds = AccessToDatabaseComp.retrieve(query);
             dgvAccountView.AutoGenerateColumns = false;
             bs.DataSource = ds.Tables[0];
           
             if (ds != null)
             {
                 if (ds.Tables[0].Rows.Count > 0)
                 {
                     dgvAccountView.DataSource = ds.Tables[0];

                     dgvAccountView.Columns[0].HeaderText = "Account ID";
                     dgvAccountView.Columns[0].Width = 50;
                     dgvAccountView.Columns[0].DataPropertyName = "AccountID";
                     dgvAccountView.Columns[0].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleLeft;

                     dgvAccountView.Columns[1].HeaderText = "Account Name";
                     dgvAccountView.Columns[1].Width = 500;
                     dgvAccountView.Columns[1].DataPropertyName = "AccountName";
                     dgvAccountView.Columns[1].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleLeft;

                     dgvAccountView.Columns[2].HeaderText = "Credit";
                     dgvAccountView.Columns[2].Width = 150;
                     dgvAccountView.Columns[2].DataPropertyName = "Credit";
                     dgvAccountView.Columns[2].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight;

                     dgvAccountView.Columns[3].HeaderText = "Debit";
                     dgvAccountView.Columns[3].Width = 150;
                     dgvAccountView.Columns[3].DataPropertyName = "Debit";
                     dgvAccountView.Columns[3].HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight;
                 }
                 else
                 {
                     dgvAccountView.DataSource = null;
                 }
             }
             else
             {
                 dgvAccountView.DataSource = null;
             }
         }
     }
     catch
     {
     }
}

数据访问类:

public class AccessToDatabaseComp
{
     private static string dbPathcomp = Application.StartupPath + "\\" + frmMain.Instance.lblDBFile.Text + ";";
     private static string conStringComp = "Data Source=" + dbPathcomp + "version=3";
     //SQLiteConnection sqliteconComp = new SQLiteConnection(conStringComp);
     private static SQLiteConnection sqlite;

     public static SQLiteConnection sqliteconComp()
     {
         if (sqlite == null)
         {
             sqlite = new SQLiteConnection(conStringComp);
         }

         if (sqlite.State != System.Data.ConnectionState.Open)
         {
             sqlite.Open();
         }
         else
         {
             sqlite.Close();
         }

         return sqlite;
     }

     public static bool insert(string query)
     {
         try
         {
             int rows = 0;
             SQLiteDataAdapter da = new SQLiteDataAdapter();
             da.InsertCommand = new SQLiteCommand(query, sqliteconComp());
             rows = da.InsertCommand.ExecuteNonQuery();

             if (rows > 0)
             {
                 return true;
             }
             else
             {
                 return false;
             }
         }
         catch
         {
             return false;
         }
     }

     public static bool update(string query)
     {
         try
         {
             int rows = 0;
             SQLiteDataAdapter da = new SQLiteDataAdapter();
             da.UpdateCommand = new SQLiteCommand(query, sqliteconComp());
             rows = da.UpdateCommand.ExecuteNonQuery();

             if (rows > 0)
             {
                 return true;
             }
             else
             {
                 return false;
             }
         }
         catch
         {
             return false;
         }
     }

     public static bool delete(string query)
     {
         try
         {
             int rows = 0;
             SQLiteDataAdapter da = new SQLiteDataAdapter();
             da.DeleteCommand = new SQLiteCommand(query, sqliteconComp());

             rows = da.DeleteCommand.ExecuteNonQuery();

             if (rows > 0)
             {
                 return true;
             }
             else
             {
                 return false;
             }
         }
         catch
         {
             return false;
         }
     }

     public static DataSet retrieve(string query)
     {
         try
         {
             SQLiteDataAdapter da1 = new SQLiteDataAdapter();
             
             da1.SelectCommand = new SQLiteCommand(query, sqliteconComp());
             DataSet ds1 = new DataSet();
             da1.Fill(ds1);
           
             return ds1;
         }
         catch
         {
             return null;
         }
     }
}

请提出一些解决方案来摆脱这个问题。

c# winforms sqlite datagridview dataset
1个回答
0
投票

首先,你确定要写这个吗:

if (string.IsNullOrEmpty(search) && !string.IsNullOrEmpty(search))
{
     query = "Select * from tblAccount";
}

有没有一个时刻

search
既空又不空?

无论如何,您已经正确地将数据与数据的显示方式分开。

从您的代码中,我了解到您始终希望显示相同的列,这些列应始终以相同的格式显示相同的属性。

那么为什么要重新初始化方法中的所有列

ViewSearch

我的建议是在构造函数中仅初始化列一次,并且仅更改数据源。

在 DataGridView 中,您想要显示一系列相似对象的各种属性,这些对象都至少有一个

AccountId
、一个
AccountName
、一个
Credit
和一个
Debit

为了以后更改后的安全,我的建议是引入一个接口

IAccount
,您想要在 DataGridView 中显示为行的每个对象至少应该实现这个接口。由于您假设该对象已经具有 AccountId、AccountName 等属性,因此这不会限制您的类的使用。

public interface IAccount         // TODO: invent a proper name
{
    int AccountId {get;}
    string AccountName {get;}
    decimal Debet {get;}
    decimal Credit {get;}
}

您的表单需要一种方法来获取必须显示的数据:

IEnumerable<IAccount> FetchAccountsToDisplay(string search)
{
    ... // do something with AccessToDatabaseComp

    // either return the fetched Accounts,
    // or return Enumerable.Empty<IAccount>();
}

如何将数据获取到

IEnumerable<IAccount>
不是这个问题的一部分。

使用 Visual Studio Designer 添加列,并定义数据的显示方式。在构造函数中定义哪一列应显示哪个属性:

public MyForm()
{
    InitializeComponent();

    // define which column should display which property:
    this.columnAccountId.DataPropertyName = nameof(IAccount.AccountId);
    this.columnAccountName.DataPropertyName = nameof(IAccount.AccountName);
    this.columnDebet.DataPropertyName = nameof(IAccount.Debet);
    this.columnCredit.DataPropertyName = nameof(IAccount.Credit);
}

您也可以使用设计器来完成此操作。使用

nameof
的优点是,如果您稍后更改属性名称而忘记更改名称,编译器会抱怨。

public ICollection<IAccount> DisplayedAccounts
{
    get => (ICollection<IAccount>)this.dataGridView1.DataSource;
    set => this.dataGridView1.DataSource = value;
}

显示数据:

void OnDisplayAccounts(string search)
{
    ICollection<IAccount> accountsToDisplay = this.FetchAccountsToDisplay(search)
        .ToList();
    this.DisplayedAccounts = accountsToDisplay;
}

然后很快!您的帐户已显示。即使没有任何帐户 (=

Enumerable.Empty<IAccount>()
),也会显示一个漂亮的空 DataGridView。

使其可编辑

上面的方法很简单,只需要几行代码。但是,操作员无法更改 DataGridView 中显示的数据。如果您需要,只需更改几行代码即可。

public interface IAccount
{
    int AccountId {get; set;}
    string AccountName {get; set;}
    decimal Debet {get; set;}
    decimal Credit {get; set;}
}

public BindingList<IAccount> DisplayedAccounts
{
    get => (BindingList<IAccount>)this.dataGridView1.DataSource;
    set => this.dataGridView1.DataSource = value;
}

void OnDisplayAccounts(字符串搜索) { IList accountToDisplay = this.FetchAccountsToDisplay(搜索) .ToList(); this.DisplayedAccounts = new BindingList(accountsToDisplay); }

现在操作员可以编辑帐户。之后,他单击“确定”按钮以表明他已完成编辑。

void ButtonOk_Clicked(object sender, ...)
{
    // fetch the edited data, as well as the original data:
    IEnumerable<IAccount> originalAccounts = ...
    IEnumerable<IAccount> editedAccounts = this.DisplayedAccounts.Cast<IAccount>();

     this.ProcessEditedAccounts(originalAccounts, editedAccounts);
}

执行一些智能 LINQ 来找出哪些帐户

  • 已删除:ID 在原始版本中,但在编辑版本中没有
  • 添加:ID已编辑,但不是原始的
  • 已更改:原始 ID 和编辑后的 ID 不同,帐户不相等

我认为完整的外部联接在这里可能很方便,但这不是问题的一部分

最后两个有用的方法:获取当前行和所有选定的行

IAccount CurrentAccount => (IAccount)((DataGridViewRow)this.dataGridView1.CurrentRow)?.DataBoundItem;

IEnumerable<IAccount> selectedAccounts = this.dataGridView1.SelectedRows
    .Cast<DataGridViewRow>()
    .Select(row => row.DataBoundItem)
    .Cast<IAccount>();
© www.soinside.com 2019 - 2024. All rights reserved.