Wydajność EF6 + WPF mvvm

0

Cześć,

Mam problem wydajnościowy podczas listowa klientów. Jak uruchamiam nowe okno CustomerListView to zanim otworzy się okno i wyświetli klientów czekam 10-15 sekund. Gdzieś mam bubla wydajnościowego, tylko nie wiem gdzie ?

Baza klientów to ok 10k wierszy + po kilka kategorii, województw i statusów

public class CustomerListViewModel : MainViewModel
    {
        private unvContext db;

        private ObservableCollection<Customer> _CustomerListCollection;
        public ObservableCollection<Customer> CustomerListCollection
        {
            get { return _CustomerListCollection; }
            set
            {
                _CustomerListCollection = value;
                RaisePropertyChanged("CustomerListCollection");
            }
        }

        private string _SearchText;
        public string SearchText
        {
            get { return _SearchText; }
            set
            {
                _SearchText = value;
                RaisePropertyChanged("SearchText");
            }
        }

        public CustomerListViewModel()
        {
            db = new unvContext();
            GetCustomers();
        }

        // Selected Customer
        private Customer _SelectedCustomer;
        public Customer SelectedCustomer
        {
            get
            {
                return _SelectedCustomer;
            }
            set
            {
                _SelectedCustomer = value;
                RaisePropertyChanged("SelectedCustomer");
            }
        }


        private void GetCustomers(string searchingtext = null)
        {
            if (String.IsNullOrWhiteSpace(searchingtext))
            {
                    db.Customer.ToList();
                CustomerListCollection = db.Customer.Local;
            }
            else
            {
                    var clc = from p in db.Customer
                              where (p.PelnaNazwaKlienta + " " + p.Miejscowosc + " " + p.Ulica + " " + p.Status.Nazwa.ToString() + " " + p.Kategoria.Nazwa.ToString()).Contains(searchingtext)
                              select p;

                CustomerListCollection = new ObservableCollection<Customer>(clc);
            }
        }

        private RelayCommand _SearchCommand;
        public RelayCommand SearchCommand
        {
            get { return _SearchCommand ?? (_SearchCommand = new RelayCommand(SearchCustomers)); }
        }
        private void SearchCustomers()
        {
            GetCustomers(_SearchText);
        }

        #region ADD / EDIT / DELETE 
        private RelayCommand _DeleteCustomerCommand;
        public RelayCommand DeleteCustomerCommand
        {
            get { return _DeleteCustomerCommand ?? (_DeleteCustomerCommand = new RelayCommand(DeleteCustomer, CanDeleteCustomerCommand)); }
        }
        private void DeleteCustomer()
        {

                Customer cst = new Customer();
                cst = db.Customer.SingleOrDefault(item => item.CustomerId == SelectedCustomer.CustomerId);
                db.Customer.Remove(cst);
                CustomerListCollection.Remove(SelectedCustomer);
                db.SaveChanges();
        }

        public bool CanDeleteCustomerCommand()
        {
            return true;
        }

        private RelayCommand _AddNewCustomerCommand;
        public RelayCommand AddNewCustomerCommand
        {
            get { return _AddNewCustomerCommand ?? (_AddNewCustomerCommand = new RelayCommand(AddCustomer)); }
        }
        private void AddCustomer()
        {
            CustomerViewModel cvm = new CustomerViewModel();
            CustomerView dv = new CustomerView();
            dv.DataContext = cvm;
            dv.ShowDialog();
            //RaisePropertyChanged("CustomerListCollection");
        }

        private RelayCommand _EditSelectedCustomerCommand;
        public RelayCommand EditSelectedCustomerCommand
        {
            get { return _EditSelectedCustomerCommand ?? (_EditSelectedCustomerCommand = new RelayCommand(EditCustomer, CanEditCustomer)); }
        }
        private void EditCustomer()
        {
            CustomerViewModel cvm = new CustomerViewModel(SelectedCustomer.CustomerId);
            CustomerView dv = new CustomerView();
            dv.DataContext = cvm;
            dv.ShowDialog();
            GetCustomers();

        }
        public bool CanEditCustomer()
        {
            if (SelectedCustomer != null)
                return true;

            return false;
        }

        #endregion
    }



 
    public class Customer : MainViewModel
    {
        [Key]
        public int CustomerId { get; set; }
        public string PelnaNazwaKlienta { get; set; }
        public string Ulica { get; set; }
        public string KodPocztowy { get; set; }
        public string Miejscowosc { get; set; }
        public string Poczta { get; set; }
        public virtual Wojewodztwo Wojewodztwo { get; set; }
        public virtual ICollection<Decydent> Decydent { get; set; }
        public virtual Category Kategoria { get; set; }
        public virtual CustomerStatus Status { get; set; }
        public virtual Employee Opiekun { get; set; }
        public virtual ICollection<CustomerGroup> CustomerGroup { get; set; }
    }

    public class CustomerStatus
    {
        [Key]
        public int CustomerStatusId { get; set; }
        public string Nazwa { get; set; }

        public virtual ICollection<Customer> Klienci { get; set; }
    }

    public class CustomerGroup
    {
        [Key]
        public int CustomerGroupId { get; set; }
        private string _Nazwa;

        public virtual ICollection<Customer> Klienci { get; set; }

        public string Nazwa
        {
            get { return _Nazwa; }
            set
            {
                if (_Nazwa != value)
                {
                    _Nazwa = value;
                }
            }
        }

    }

    public class Category
    {
        [Key]
        public int CategoryId { get; set; }
        public string Nazwa { get; set; }

        public virtual ICollection<Customer> Klienci { get; set; }
    }
 
 
<Controls:MetroWindow x:Class="str.View.CustomerListView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
             xmlns:v="clr-namespace:str.View" 
             xmlns:vm="clr-namespace:str.ViewModel"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
             x:Name="klvm"
             Height="Auto" Width="Auto">
    <Window.DataContext>
        <vm:CustomerListViewModel/>
    </Window.DataContext>


    <StackPanel Width="Auto" Height="Auto" HorizontalAlignment="Center" Orientation="Vertical">
        <StackPanel.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Dodaj nowego" Command="{Binding AddNewCustomerCommand, UpdateSourceTrigger=PropertyChanged}"/>
                <MenuItem Header="Edytuj" Command="{Binding EditSelectedCustomerCommand, UpdateSourceTrigger=PropertyChanged}"/>
                <MenuItem Header="Usuń" Command="{Binding DeleteCustomerCommand, UpdateSourceTrigger=PropertyChanged}"/>
            </ContextMenu>
        </StackPanel.ContextMenu>
        <StackPanel>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Label Grid.Row="0" Grid.Column="0" Content="Wyszukaj" HorizontalAlignment="Left" />
                <TextBox Grid.Row="0" Grid.Column="1" MinWidth="200" HorizontalAlignment="Stretch" Margin="0 0 0 0" VerticalAlignment="Stretch" 
                     Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
                <Button Grid.Row="0" Grid.Column="2" Content="szukaj" Command="{Binding SearchCommand}" IsDefault="True" />
            </Grid>
            
        </StackPanel>
        <ListView x:Name
="lvCustomers" ItemsSource="{Binding Path=CustomerListCollection, UpdateSourceTrigger=PropertyChanged}" 
              SelectedItem="{Binding Path=SelectedCustomer}" Width="Auto" Height="300">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="NAZWA KONTRAHENTA">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Margin="0 0 0 0" Width="200">
                                    <TextBlock x:Name="txPelnaNazwaKlienta" Text="{Binding PelnaNazwaKlienta, UpdateSourceTrigger=PropertyChanged}"/>
                                </StackPanel>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Ulica">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Margin="0 0 0 0">
                                    <TextBlock x:Name="txUlica" Text="{Binding Ulica,  UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"/>
                                </StackPanel>

                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Miejscowość">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Margin="0 0 0 0">
                                    <TextBlock Text="{Binding Miejscowosc, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
                                </StackPanel>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Województwo">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Margin="0 0 0 0">
                                    <TextBlock Text="{Binding Wojewodztwo.Nazwa}"/>
                                </StackPanel>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Telefon">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Margin="0 0 0 0">
                                    <TextBlock Text="{Binding Telefon, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
                                </StackPanel>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Status">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Margin="0 0 0 0">
                                    <TextBlock Text="{Binding Status.Nazwa, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"/>
                                </StackPanel>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
    </StackPanel>

    </Controls:MetroWindow>
1

A czemu pobierasz na raz wszystkich klientów? Pobierz tyle rekordów ile jest sens wyświetlić użytkownikowi, a nie wszystkich.

0

db.Customer.ToList(); to chyba jakiś żart? Zastanawiałeś się, co się stanie jeśli będziesz - hipotetycznie - mieć 50k albo 100k klientów?
BTW like (na który w sql jest tłumaczona metoda Contains()) jest bardzo powolną operacją, chyba jedną z najwolniejszych dostępnych w sql; wymaga przeskanowania całej tabeli lub odpowiedniego indeksu (Clustered Index Scan/Index Scan), a Ty jeszcze skanujesz po złączeniu z trzech tabel, nic dziwnego, że działa powoli. Zobacz sobie plan zapytania (SQL Profiler'em wyciągniesz treść zapytania idącą do bazy, w Management Studio zobaczysz plan zapytania) i zobacz, ile masz tam skanów. Potem po poprawkach sprawdź ponownie jak wygląda sql, jak zmienił się plan zapytania i jak spadł koszt zapytania (który jest kluczowy, wartości powyżej ~0.1-10 świadczą o słabym zapytaniu, Ty możesz mieć około 100).
Ponadto nie wziąłeś pod uwagę, że ktoś może wpisać "Szawa Nie" i otrzyma wynik z Warszawa, Niepodległości, który nijak ma się do szukanej treści.

1 użytkowników online, w tym zalogowanych: 0, gości: 1