3

I am developing my first WPF browser application.

I load invoices in a dataGrid then I filter with textBox or comboBox.

Because it takes few seconds to load, I'am trying to put a loading animation according the following example:

here

It doesn't work the first time I navigate to the page. My dataGrid remains empty. When I debug I have this following error which happens on my query in Get() function.

'System.Data.Entity.Core.EntityCommandExecutionException' occurred in mscorlib.dll but was not handled in user code

But the this query used to work well before I made the changes for the animation. So maybe the problem doesn't come from the query.

enter image description here

Exception:Thrown: "Connection must be valid and open." (System.InvalidOperationException) A System.InvalidOperationException was thrown: "Connection must be valid and open." Time: 11/20/2015 12:36:31 PM Thread:Worker Thread[13324]

public class ConsultInvoiceViewModel : ViewModelBase
{

    public Context ctx = new Context();

    private ICollectionView _dataGridCollection;
    private string _filterString;
    private ObservableCollection<Invoice> invoiceCollection;


    public ConsultInvoiceViewModel()
    {
        if (!WPFHelper.IsInDesignMode)
        {
            var tsk = Task.Factory.StartNew(InitialStart);
            tsk.ContinueWith(t => { MessageBox.Show(t.Exception.InnerException.Message); }, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, TaskScheduler.FromCurrentSynchronizationContext());
        }
    }

    private void InitialStart()
    {
        try
        {
            State = StateEnum.Busy;
            DataGridCollection = CollectionViewSource.GetDefaultView(Get());
            DataGridCollection.Filter = new Predicate<object>(Filter);
            GetShop(); //load one comboBox
            GetSupplier(); //load one comboBox
        }
        finally
        {
            State = StateEnum.Idle;
        }

    }

    private ObservableCollection<Invoice> Get()
    {
        DateTime date2 = DateTime.Now.AddMonths(-2);

        var query = ctx.Invoices
                    .GroupBy(x => new { x.suppInvNumber, x.shop1, x.date, x.foodSupplier })
                    .ToList()
                    .Select(i => new Invoice
                    {
                        suppInvNumber = i.Key.suppInvNumber,
                        shop1 = i.Key.shop1,
                        date = i.Key.date,
                        foodSupplier = i.Key.foodSupplier,
                        totalPrice = i.Sum(t => t.totalPrice),
                    })
                    .Where(d => d.date >= date2)
                    .OrderByDescending(d => d.date)
                    .AsQueryable();

        invoiceCollection = new ObservableCollection<Invoice>(query);

        return invoiceCollection;
    }

    public ICollectionView DataGridCollection
    {
        get
        { 
            return _dataGridCollection; 
        }
        set 
        { 
            _dataGridCollection = value; 
            OnPropertyChanged("DataGridCollection"); }
    }

    public string FilterString
    {
        get 
        { 
            return _filterString; 
        }
        set 
        {
            _filterString = value;
            OnPropertyChanged("FilterString");
            FilterCollection();
        }
    }


    public static readonly PropertyChangedEventArgs StateArgs = ViewModelBase.CreateArgs<ConsultInvoiceViewModel>(c => c.State);
    private StateEnum _State;

    public StateEnum State
    {
        get
        {
            return _State;
        }
        set
        {
            var oldValue = State;
            _State = value;
            if (oldValue != value)
            {
                OnStateChanged(oldValue, value);
                OnPropertyChanged(StateArgs);
            }
        }
    }

    protected virtual void OnStateChanged(StateEnum oldValue, StateEnum newValue)
    {
    }



    private void FilterCollection()
    {
        if (_dataGridCollection != null)
        {
            _dataGridCollection.Refresh();
        }
    }

    private bool Filter(object obj)
    {
        var data = obj as Invoice;

        if (data != null)
        {
            if (!string.IsNullOrEmpty(_filterString))
            {
                return data.suppInvNumber.Contains(_filterString);

            }
            return true;
        }
        return false;
    }

    private void SearchFilter()
    {
        IOrderedEnumerable<Invoice> invs;
        invs = ctx.Invoices
                   .Where(s => s.shop == Shop && s.supplier == Supplier && s.date >= From && s.date <= To)
                   .GroupBy(x => new {x.suppInvNumber, x.shop1, x.date, x.foodSupplier })
                   .ToList()
                   .Select(i => new Invoice
                   {
                       suppInvNumber = i.Key.suppInvNumber,
                       shop1 = i.Key.shop1,
                       date = i.Key.date,
                       foodSupplier = i.Key.foodSupplier,
                       totalPrice = i.Sum(t => t.totalPrice),
                   })
                   .OrderByDescending(d => d.date);
        }

        invoiceCollection.Clear();
        if (invs != null)
           foreach (var inv in invs)
           {
               invoiceCollection.Add(inv);
           }     
        FilterCollection();   
    }

    #region combobox
    private void GetShop()
    {
        ctx.shops.ToList().ForEach(shop => ctx.shops.Local.Add(shop));
        SShop = ctx.shops.Local;
    }

    private void GetSupplier()
    {
        ctx.foodSuppliers.ToList().ForEach(supplier => ctx.foodSuppliers.Local.Add(supplier));
        FoodSupplier = ctx.foodSuppliers.Local;
    }


    private IList<foodSupplier> supplier;

    public IList<foodSupplier> FoodSupplier
    {
        get
        {
            if (supplier == null)
            GetSupplier();
            return supplier;
        }
        set
        {
            supplier = value;
            OnPropertyChanged("FoodSupplier");
        }
    }

    private IList<shop> shop;

    public IList<shop> SShop
    {
        get
        {
            return shop;
        }
        set
        {
            shop = value;
            OnPropertyChanged("SShop");
        }
    }


    private int _shop;

    public int Shop
    {
        get
        {
            return _shop;
        }
        set
        {
            _shop = value;
            OnPropertyChanged("Shop");
            SearchFilter();
        }
    }

    private int _supplier;

    public int Supplier
    {
        get
        {
            return _supplier;
        }
        set
        {
            _supplier = value;
            OnPropertyChanged("Supplier");
            SearchFilter();
        }
    }

    #endregion

    #region "Command"

    private ICommand searchCommand;

    public ICommand SearchCommand
    {
        get
        {
            return searchCommand ?? (searchCommand = new RelayCommand(p => this.Search(), p => this.CanSearch()));
        }
    }

    private bool CanSearch()
    {
       return true;
    }

    #endregion
}
Cantinou
  • 126
  • 5
  • 21
  • 1
    My guess is it's a problem with the call to `.AddDate`. Entityframework doesn't know how to translate that in to sql. Try precalculating that date outside the query to a simple date variable and using that. – Bradley Uffner Nov 20 '15 at 03:54
  • check this http://stackoverflow.com/questions/31118257/an-exception-of-type-system-data-entity-core-entitycommandexecutionexception-o –  Nov 20 '15 at 03:56
  • and this http://stackoverflow.com/questions/25582291/a-first-chance-exception-of-type-system-data-entity-core-entitycommandexecution –  Nov 20 '15 at 03:56
  • @Bradley Uffner I changed it, but the problem is still there. This query worked fine before I made the changes to put this animation. – Cantinou Nov 20 '15 at 04:01
  • Possible duplicate of [LINQ to Entities with AddMonth method](http://stackoverflow.com/questions/3529361/linq-to-entities-with-addmonth-method) – Mick Nov 20 '15 at 04:13
  • Your question doesn't adequately identify the error. All you've mentioned is the type of the exception. You need to supply the exception's message, the stack trace and the line on which the error is occurring. – Mick Nov 20 '15 at 04:15
  • Now you need to provide the InnerException. – Bradley Uffner Nov 20 '15 at 04:27
  • @Bradley Uffner, It's done – Cantinou Nov 20 '15 at 04:48
  • 1
    This error indicates a problem connecting to the database, I just noticed that you are opening your database context at application start and are keeping that same reference around forever. This a pretty big anti-pattern and can lead to all sorts of issues. You should wrap each of your logical operations in its own Context instance, preferably in a `using` block. – Bradley Uffner Nov 20 '15 at 04:58

1 Answers1

2

The exception you are getting indicates an error connecting to the database. It's hard to diagnose this because of the way you keep a single Context reference for the life of the application. That connection could be failing at any point.

Try wrapping your data access in a new Context for each logical operation like this. Keeping one Context around for the life of an application is an Anti-pattern that can lead to all kinds of errors, especially when trying to do things in the background.

  private ObservableCollection<Invoice> Get()
    {
        using (var ctx = new Context())
        {
        DateTime date2 = DateTime.Now.AddMonths(-2);

        var query = ctx.Invoices
                    .GroupBy(x => new { x.suppInvNumber, x.shop1, x.date, x.foodSupplier })
                    .ToList()
                    .Select(i => new Invoice
                    {
                        suppInvNumber = i.Key.suppInvNumber,
                        shop1 = i.Key.shop1,
                        date = i.Key.date,
                        foodSupplier = i.Key.foodSupplier,
                        totalPrice = i.Sum(t => t.totalPrice),
                    })
                    .Where(d => d.date >= date2)
                    .OrderByDescending(d => d.date)
                    .AsQueryable();

        invoiceCollection = new ObservableCollection<Invoice>(query);
        }
        return invoiceCollection;
    }
Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76