LINQ to SQL разделительные фильтры для лучшей производительности - PullRequest
2 голосов
/ 18 июля 2011

У меня есть эти ниже LINQ to SQL запросы

var kayitlarFiltreli = from rows in db.TBLP1CARIs
                       orderby rows.ID descending
                       where rows.HESAPADI.ToLower().Contains(filter.ToLower()) ||
                                              (rows.CARITURU == "Bireysel" ?
                                               rows.B_ADSOYAD.ToLower().Contains(filter.ToLower()) :
                                               rows.K_FIRMAADI.ToLower().Contains(filter.ToLower())) ||
                                               rows.ID.ToString().Contains(filter)
                       select rows;

var kayitlarBakiyeli = from rows in kayitlarFiltreli
                       select new
                                   {
                                       HESAPNO = rows.ID,
                                       HESAPADI = rows.HESAPADI,
                                       CARIADI = (rows.CARITURU == "Bireysel" ? rows.B_ADSOYAD : rows.K_FIRMAADI),
                                       Bakiye = get_bakiye(rows.ID, rows.LISTEPARABIRIMI)
                                   };

var kayitlarSon = from rows in kayitlarBakiyeli
                  select new
                            {  rows.HESAPNO,
                               rows.HESAPADI,
                               rows.CARIADI,
                               Bakiye = rows.Bakiye.Contains(".") == true ?
                                        rows.Bakiye.TrimEnd('0').TrimEnd('.') :
                                        rows.Bakiye

                            };

У меня проблема с производительностью. Я имею в виду ответ на запросы, по крайней мере, после 15 секунд, и когда он развертывается на веб-сайте, он занимает как минимум 5 секунд длястраница, которая использует эти запросы для заполнения GridView. get_bakiye(p1,p2,..), является длинным методом с for, foreach и запросом Linq-to-SQL. Я думаю, что большая часть времени потраченана get_bakiye Я уже боролся с этим и сократил время отклика примерно на 2 секунды, однако оно все еще медленное. И я пытаюсь заставить вышеупомянутые запросы работать быстрее.

Я пытался

var kayitlarSirali =  from rows in db.TBLP1CARIs
                      orderby rows.ID descending
                      select rows;

var kayitlarFiltreli = from rows in kayitlarSirali
                       where rows.HESAPADI.ToLower().Contains(filter.ToLower()) ||
                                        (rows.CARITURU == "Bireysel" ? 
                                         rows.B_ADSOYAD.ToLower().Contains(filter.ToLower()) : 
                                         rows.K_FIRMAADI.ToLower().Contains(filter.ToLower())) ||
                                         rows.ID.ToString().Contains(filter)
                       select rows;

А в остальном то же самое.По сути, я только что отделил фильтрующую часть с Contains(), что я не уверен, если это так сильно поможет.

Хорошо ли разделять where Я имею в виду фильтры при запросах к базе данных, и так ли это?для производительности лучше один раз запросить базу данных и получить результаты в IQueryable в памяти, а все остальное сделать на ней?

Что вы посоветуете для того, чтобы эти запросы работали быстрее?Это метод get_bakiye(), который я написал не полностью, но я должен заставить его работать быстрее.

public static string get_bakiye(int cari_id, string birim_kod)
        {
            return get_bakiye(cari_id, DAL.DAOCari.GetEntity(cari_id).LISTEPARABIRIMI, null,false);
        }

public static string get_bakiye(int cari_id, string birim_kod, List<BAL.P_CariBakiyeTablosu> custom_rapor, bool borcluTespit)
        {
            VeriyazDBDataContext db = new VeriyazDBDataContext(); db.Connection.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["LocalSqlServer"].ConnectionString;

            decimal return_bakiye = 0;

            if (birim_kod == null || birim_kod.Trim() == "") //default
                birim_kod = "TL";

            //devir bakiyesini hesapla:
            List<BAL.P_CariBakiyeTablosu> bakiyeler = new List<BAL.P_CariBakiyeTablosu>();
            if (custom_rapor == null)
                bakiyeler = CariBakiyeRaporuOlustur(cari_id, true);
            else
                bakiyeler = custom_rapor;

            bakiyeler.RemoveAt(0);

            List<TBLP1DOVIZTANIMLARI> dovizTanimlariTumListe = DAL.DAOdoviztanimlari.SelectAll().ToList();
            //devirleri hesaplarken döviztanimlari tablosundaki varsayılan kuru kullanıyor
            for (int i = 0; i < bakiyeler.Count; i++)
            {
                if (bakiyeler[i].DOVIZ == birim_kod)
                {
                    return_bakiye = return_bakiye + Convert.ToDecimal(bakiyeler[i].DEVIR);
                }
                else
                {
                    decimal from_kur = 1;
                    from_kur = from_kur = dovizTanimlariTumListe.Where(rows => rows.TBLP1DOVIZLER.KOD == bakiyeler[i].DOVIZ).FirstOrDefault().VARSAYILANKUR.GetValueOrDefault(1);

                    decimal to_kur = 1;
                    to_kur = dovizTanimlariTumListe.Where(rows => rows.TBLP1DOVIZLER.KOD == birim_kod).First().VARSAYILANKUR.GetValueOrDefault(1);


                    return_bakiye = return_bakiye + (Convert.ToDecimal(bakiyeler[i].DEVIR) * (from_kur / to_kur));
                }
            }

            //islem bakiyesini hesapla:

            var islemler = from rows in db.TBLP1ISLEMs
                           where
                           rows.CARI_ID == cari_id &&
                           rows.TEKLIF.GetValueOrDefault(false) == false &&
                           rows.SOZLESME.GetValueOrDefault(false) == false &&
                           (rows.SIPARISDURUMU == "İşlem Tamamlandı" || 
                            rows.SIPARISDURUMU == "Hazırlanıyor" || 
                            rows.SIPARISDURUMU == "" || 
                            rows.SIPARISDURUMU == null)
                           select rows;

            //var dovizKuruOlanIslemler = from dovizKuruRow in db.TBLP1DOVIZKURUs
            //                            select dovizKuruRow.ISLEM_ID;

            foreach (var item in islemler)
            {
                decimal from_kur = 1;
                decimal fromKurVarsayilan = 1;
                //belirtilen dövizin varsayılanını çekiyor
                fromKurVarsayilan = dovizTanimlariTumListe.Where(rows => rows.TBLP1DOVIZLER.KOD == item.PARABIRIMI).FirstOrDefault().VARSAYILANKUR.GetValueOrDefault(1);

                try
                {
                    from_kur = item.KURDEGERI.Value;
                    //aşağıdaki satırda dövizkuru tablosundan işleme ait kuru çekerek hesap yapıyordu, işlem tablosuna KURDEGERİ kolonu ekleyince
                    //buna gerek kalmadı, yukarıdaki satırda işleme ait kur değeri işlem tablosundan çekiyor.
                    //from_kur = item.TBLP1DOVIZKURUs.Where(rows => rows.DOVIZBIRIM == item.PARABIRIMI).FirstOrDefault().KUR.GetValueOrDefault();
                }
                catch
                {
                    from_kur = fromKurVarsayilan;
                }

                //carinin para biriminin varsayılan kurunu çekiyor
                decimal to_kur = 1;
                decimal toKurVarsayilan = 1;

                toKurVarsayilan = dovizTanimlariTumListe.Where(rows => rows.TBLP1DOVIZLER.KOD == birim_kod).FirstOrDefault().VARSAYILANKUR.GetValueOrDefault(1);

                to_kur = toKurVarsayilan;


                if (item.CARIISLEMTURU == "BORC")
                {
                    return_bakiye = return_bakiye + (Convert.ToDecimal(item.GENELTOPLAM) * (from_kur / to_kur));
                }
                if (item.CARIISLEMTURU == "ALACAK")
                {
                    return_bakiye = return_bakiye - (Convert.ToDecimal(item.GENELTOPLAM) * (from_kur / to_kur));
                }
            }

            string returnBakiyeParaFormatli = DAL.Format.ParaDuzenle.ParaFormatDuzenle(return_bakiye.ToString());
            if (borcluTespit==true)
            {
                return return_bakiye.ToString();
            }
            if (returnBakiyeParaFormatli.Contains(".") == true)
            {
                return returnBakiyeParaFormatli.TrimEnd('0').TrimEnd('.') + " " + birim_kod;

            }
            else
            {
                return returnBakiyeParaFormatli + " " + birim_kod;
            }

        }
    }

Ответы [ 2 ]

3 голосов
/ 18 июля 2011

В общем, я думаю, вам нужно понять, что заставляет Linq to Sql выполнить запрос к вашей базе данных.В общем, методы расширения, такие как ToList(), First(), FirstOrDefault(), Single(), заставят Linq To Sql выполнить команду для базы данных.Одна строка, которая меня беспокоит:

List<TBLP1DOVIZTANIMLARI> dovizTanimlariTumListe = DAL.DAOdoviztanimlari.SelectAll().ToList();

Это, кажется, получает каждую строку из таблицы базы данных, на которую отображается DAOdoviztanimlari.Результат этого затем запрашивается в памяти.

Это происходит для каждой записи в запросах, которые вызывают get_bakiye()!

В конечном счете (идеальный мир), который вы хотите, чтобы get_bakiye() не содержаллюбой из методов расширения, которые я упомянул, и для возврата IQueryable<string> затем позвольте Linq to SQL решить, как он оптимизирует и выполняет SQL.

1 голос
/ 18 июля 2011

Сначала профилируйте вашу базу данных и посмотрите, сколько времени потребуется для выполнения сгенерированных запросов и как часто они выполняются.

Если результаты профилирования показывают, что вы выполняете тот же запрос к базе данных, или запрос выполняется слишком долго, возможно, вам следует рассмотреть возможность загрузки значений в память и доступа к ним оттуда. Или даже рассмотрите скомпилированные запросы как альтернативу, если это правдоподобно.

Некоторое время назад у меня была похожая проблема, которую я решил, создав отдельный класс, который обрабатывает загрузку нужных мне значений в коллекцию и обновляет значения при необходимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...