How to properly switch between identical databases on the go ?

don bradman 621 Reputation points
2022-12-01T04:26:09.297+00:00

I have multiple databases in my WPF app, different databases for different years e.g. 2020.db, 2021.db, 2022.db etc . I have a combo box whose Items are a list of years (2020, 2021, 2022 ...).

When I select a year from the said combo box I want the database of the entire app to change to that years database and update the UI and items inside the viewmodel class and wherever the database queries are called.

All the databases are identical i.e. the table names, column names and datatypes of the table columns are all same just the data is different.

Currently in my app I have declared a string containing the path of the database like

namespace test  
{  
      
    public static class DB  
    {  
        public static string dbloc = @"Data Source=2022.db";  
    }  
  
    public partial class Window1 : Window  
    {  
          
          
        public Window1()  
        {  
            InitializeComponent();  
  
            this.DataContext = new BillsViewModel();  
        }  
  
    }  
    ...  
}  

and I use it like using (var connection = new SQLiteConnection(DB.dbloc)) or something similar inside different methods of the BillsViewModel and other classes wherever required.

Also, inside BillsViewModel I have declared many properties that act as ItemSource of vairous controls like datagrid's, textbox's, combobox's, button's etc. which basically takes data from the database.

So, when I change the selection from the above mentioned combo box those properties also need to get fresh updates from the newly chosen database.

Is it possible to use a switch statement to effectively change the database on combo box selection (something like below) ?

switch (comboboxSelectedItem)  
    {  
        case "2020":  
            dbloc = @"Data Source=2020.db";  
            break;  
  
        case "2021":  
            dbloc = @"Data Source=2021.db";  
            break;  
  
        default:  
            dbloc = @"Data Source=2022.db";  
            break;  
    }  

But the propeties in the BillsViewModel also needs to update i.e. get data from a different database now. If I add a new instance of the BillsViewModel class before the break in above switch statement will that work.

What is the proper way of doing this ? Can anyone help ?

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,665 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,191 questions
XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
760 questions
0 comments No comments
{count} votes

2 additional answers

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2022-12-01T18:57:53.647+00:00

    Hi,
    build Model for access to database with public property for "Data Source".

    if you change database in ViewModel set new public property for "Data Source" in Model, than clear collections (set Source to null) and execute PropertyChanged for Views or with empty string (refresh all objects in UI). Refreshing UI will get Views and in getter you check Source of collection for reloading data.

    Or in CodeBehind like in following demo:

    XAML:

    <Window x:Class="WpfApp1.Window031"  
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
            xmlns:local="clr-namespace:WpfApp1"  
            mc:Ignorable="d"  
            Title="Window031" Height="450" Width="800">  
      <Grid>  
        <Grid.RowDefinitions>  
          <RowDefinition Height="Auto"/>  
          <RowDefinition/>  
        </Grid.RowDefinitions>  
        <ComboBox x:Name="cb" SelectionChanged="cb_SelectionChanged" Margin="5" Width="200">  
          <ComboBoxItem>2020</ComboBoxItem>  
          <ComboBoxItem>2021</ComboBoxItem>  
          <ComboBoxItem>2022</ComboBoxItem>  
        </ComboBox>  
        <DataGrid ItemsSource="{Binding View}" Grid.Row="1" Margin="5"/>  
      </Grid>  
    </Window>  
    

    CodeBehind:

    using System;  
    using System.Collections.ObjectModel;  
    using System.ComponentModel;  
    using System.Data;  
    using System.Data.SQLite;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Data;  
      
    namespace WpfApp1  
    {  
      /// <summary>  
      /// Interaction logic for Window031.xaml  
      /// </summary>  
      public partial class Window031 : Window, INotifyPropertyChanged  
      {  
        public Window031()  
        {  
          InitializeComponent();  
          this.DataContext = this;  
        }  
      
        private void cb_SelectionChanged(object sender, SelectionChangedEventArgs e)  
        {  
          var comboboxSelectedItem = ((ComboBoxItem)cb.SelectedValue).Content;  
          switch (comboboxSelectedItem)  
          {  
            case "2020":  
              dbloc = @"Data Source=2020.db";  
              break;  
      
            case "2021":  
              dbloc = @"Data Source=2021.db";  
              break;  
      
            default:  
              dbloc = @"Data Source=2022.db";  
              break;  
          }  
        }  
      
        private string _dbloc;  
        string dbloc  
        {  
          get => this._dbloc;  
          set  
          {  
            if (this._dbloc != value)  
            {  
              this._dbloc = value;  
              LoadData();  
              OnPropertyChanged(nameof(View));  
            }  
          }  
        }  
      
        ObservableCollection<Data> col = new ObservableCollection<Data>();  
        CollectionViewSource cvs = new CollectionViewSource();  
      
        public ICollectionView View { get => cvs.View; }  
      
        private void LoadData()  
        {  
          using (SQLiteDataAdapter sda = new SQLiteDataAdapter("SELECT * FROM Tab1", dbloc))  
          {  
            DataTable dt = new DataTable();  
            sda.Fill(dt);  
            col.Clear();  
            foreach (DataRow row in dt.Rows)  
            {  
              col.Add(new Data()  
              {  
                ID = Convert.ToInt32(row["ID"]),  
                Name = (string)row["Name"],  
                Description = (string)row["Description"]  
              });  
            }  
          }  
      
          cvs.Source = col;  
        }  
      
        public event PropertyChangedEventHandler? PropertyChanged;  
        internal void OnPropertyChanged(string propertyName) =>   
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));  
      }  
      
      public class Data  
      {  
        public int ID { get; set; }  
        public string Name { get; set; }  
        public string Description { get; set; }  
      }  
    }  
    
    
    
      
    

  2. Hui Liu-MSFT 37,946 Reputation points Microsoft Vendor
    2022-12-02T10:01:57.763+00:00

    As Peter said, I used Sql Server database for testing, you could refer to the code below to use Sqlite.

    Xaml:

    <Window.DataContext>  
            <local:ViewModel/>  
        </Window.DataContext>  
        <Window.Resources>  
           
        </Window.Resources>  
        <Grid>  
            <Grid.ColumnDefinitions>  
                <ColumnDefinition Width="150"/>  
                <ColumnDefinition/>  
            </Grid.ColumnDefinitions>  
            <ComboBox Name="cb"  Width="100" Height="50" ItemsSource="{Binding Items}"  SelectedValuePath="ConStr" DisplayMemberPath="Name"      
                      SelectedValue="{Binding SelectedItem, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>  
            <DataGrid x:Name="dt" Grid.Column="1" Width="300" Height="300" ItemsSource="{Binding BillsView}" AutoGenerateColumns="False">  
                <DataGrid.Columns>  
                    <DataGridTextColumn Header="Id" Binding="{Binding Id, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>  
                    <DataGridTextColumn Header="Party" Binding="{Binding Party, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>  
                </DataGrid.Columns>  
            </DataGrid>  
        </Grid>  
    

    Codebehind:

    266575-combobox-refersh-datagrid-data.txt

    The result:
    266604-8.gif

    Update:

    <TabItem  
     Header="Dashboard"  
     Name="default"  
     Background="{DynamicResource Darkish}"  
     Foreground="AntiqueWhite"  
     HorizontalContentAlignment="Center"  
     VerticalAlignment="Stretch"  
     Width="180"  
     HorizontalAlignment="Center"  
     FontFamily="Leelawadee UI"  
     FontSize="20"  
     Margin="0,0,0,0"  
     Padding="0,0,0,0">  
                            <Border  
     Background="{DynamicResource Darkish}"  
     Margin="0,0,0,0"  
     Padding="0,0,0,0"  
     HorizontalAlignment="Center"  
     VerticalAlignment="Stretch"  
     Width="{Binding ElementName=grid,Path=ActualWidth}">  
                                <Grid>  
                                   ...  
                                    <DataGrid ItemsSource="{Binding BillsView}"  
     ...>  
                                        <DataGrid.Columns>  
                                         ...  
      
                                        </DataGrid.Columns>  
                                        
                                    </DataGrid>  
                                    <StackPanel Grid.Row="2">  
                                        <ComboBox  x:Name="cb"  Width="100" Height="50" ItemsSource="{Binding Items}"    SelectedValuePath="ConStr" DisplayMemberPath="Name"      
                       SelectedValue="{Binding Tab1SelectedItem, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />  
                                    </StackPanel>  
                                </Grid>  
                            </Border>  
    </TabItem>  
    

    Codebehind:

    268477-comboboxchangedatasource.txt

    The result:

    268482-9.gif

    ----------------------------------------------------------------------------

    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.