Quantcast
Channel: VBForums
Viewing all articles
Browse latest Browse all 15038

Async in ViewModel - best practices

$
0
0
Hello everyone,

I'm using View-model first approach. In project that I'm currently working on I have a lot of cases where I need to fetch data from DB. Data is being used for binding controls (DataGrid, Textbox's Text etc...).

Mostly I need that to be done immediately when view is displayed - like open a view with filled DataGrid or showing notifications with Text data.

To do It smoothly in UI I had to create some sort of asynchronous solutions. Because I like things short and simple, I did this:

Example of how my code works (not including .xaml, there might be some typo mistakes):

Code:

public class MyModel //Model class
{
    public string Name { get; set; }
    public string SurName  { get; set; }
}

public class MainWindowViewModel : BaseViewModel // Viewmodel, class from which I call data (BaseViewmodel class just inherits INotifyProperty interface)
{
  private bool loading_animation; //Boolean for showing loading animation
  private readonly MyProcedures _procedures

  public MainWindowViewModel()
  {
      _procedures= new MyProcedures();

        Task.Run(()=> Load_data());
  }
   
  //Property which holds data for binding to UI controls 
  private ObservableCollection<MyModel> _persons;
  public ObservableCollection<MyModel> Persons
  {
      get { return _persons; }
      set { _persons = value; OnPropertyChanged(); }
  }
   
  private void Load_data()
  {
      loading_animation=true; //start animation in UI
 
      Person = _procedures.GetAllEmployees(12).Result; //Get all employees from department 12

      if(Person==null)
      {
          loading_animation=false;
          return;
      }
      else
      {
        loading_animation=false;
      }
  }
}

public class MyProcedures //Class, which holds DB logic
{
             
  public Task<ObservableCollection<MyModel>> GetAllEmployees(int department_id)
  {
      var employees_list = new ObservableCollection<MyModel>();

      try
      {
          using (OracleConnection conn = new OracleConnection(conn_string))
          {
            conn.Open();

            using (OracleCommand cmd = new OracleCommand("MySchema.MyProcedure",conn))
            {
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.Parameters.Add("department_in", OracleDbType.Decimal).Value = department_id;
                cmd.Parameters.Add("result", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
                         
                using (OracleReader rdr = new OracleReader(cmd.ExecuteReader()))
                {
                    while (await rdr.ReadAsync())
                    {
                      employees_list.Add(new MyModel()
                      {
                          Name= rdr[0] as string ?? null,
                          Surname= rdr[1] as string ?? null
                        }
                    }   
                }
            }     
        }
        return employees_list; 
      }
      catch Exception ex
      {
        MessageBox.Show(ex.Message);
           
        return null; 
      }
}

In short – I fill ObservableCollection of type T in async/await Task in my ViewModel constructor with Task.Run. That results in a smooth UI display with loading animation, and when data is obtained from DB, loading animation stops and my UI controls get's updated with binding.

If anything goes wrong when querying DB I get error back, and whole code stops.

So, generally speaking, is this approach good ? Or is there a better way of doing It – considering deadlocks,memory leaks or any kind of hidden errors that I'm not aware of?

Viewing all articles
Browse latest Browse all 15038

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>