优化LINQ查询,检查结果是否有值

时间:2013-04-17 03:39:01

标签: c# database linq

我有LINQ查询检查查询结果并结束语句。该数据库有大约600k的数据。以下是LINQ查询和if语句。

 var feetypelist = from feetype in dbDataContext.tbl_fee_types
                          orderby feetype.seq
                          select feetype.id;

        foreach (var fty in feetypelist)
        {
            var checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                  where fee.arr == arr && fee.dep == dep && fee.feetypeid == fty && fee.site_id == siteId
                                  orderby fee.seq
                                  select fee;

            if (checkFeeCharges.Count() == 0)
            {
                checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                  where fee.arr == arr && fee.dep == dep && fee.feetypeid == fty && fee.site_id == siteId
                                  && fee.country == country
                                  orderby fee.seq
                                  select fee;
            }

            if (checkFeeCharges.Count() == 0)
            {
                checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                  where fee.site_id == siteId && fee.country == country && 
                                  ((fee.arr == arr && fee.dep == dep) || (fee.arr.Equals("DOM") && fee.dep.Equals("DOM")) ||
                                  (fee.arr.Equals("*") && fee.dep == dep) || (fee.arr == arr &&  fee.dep.Equals("*")))
                                  && fee.feetypeid == fty
                                  orderby fee.seq
                                  select fee;

                if (checkFeeCharges.Count() == 0)
                {
                    var country_route = from route in dbDataContext.tbl_country_routes
                                        where route.origin_airport_cd == arr && route.destination_airport_cd == dep
                                        select route;

                    if (country_route.Count() >= 1)
                    {
                        foreach (var c in country_route)
                        {
                            if (c.air_asiax == 'Y')
                            {
                                //con_flight = "Y";
                                checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                                  where fee.site_id == siteId && fee.country == country &&
                                                  ((fee.arr == "AAX" && fee.dep == "AAX") || (fee.arr == "*" && fee.dep == dep) ||
                                                  (fee.arr == arr && fee.dep == "*")) && fee.feetypeid == fty
                                                  orderby fee.seq
                                                  select fee;

                                if (checkFeeCharges.Count() == 0)
                                {
                                    checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                                      where fee.site_id == siteId && fee.country == country &&
                                                      ((fee.arr == arr && fee.dep == dep) || (fee.arr == "INT" && fee.dep == "INT") ||
                                                      (fee.arr == "*" && fee.dep == dep) || (fee.arr == arr && fee.dep == "*") ||
                                                      (fee.arr == country && fee.dep == country)) &&
                                                      fee.feetypeid == fty
                                                      orderby fee.seq
                                                      select fee;
                                }
                            }
                            else
                            {
                                checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                                  where fee.site_id == siteId && fee.country == country &&
                                                  ((fee.arr == arr && fee.dep == dep) || (fee.arr == "INT" && fee.dep == "INT") ||
                                                  (fee.arr == "*" && fee.dep == dep) || (fee.arr == arr && fee.dep == "*") ||
                                                  (fee.arr == country && fee.dep == country)) &&
                                                  fee.feetypeid == fty
                                                  orderby fee.seq
                                                  select fee;
                            }

                        }
                    }
                    else
                    {
                        checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                          where fee.site_id == siteId && fee.country == country &&
                                          ((fee.arr == arr && fee.dep == dep) || (fee.arr == "INT" && fee.dep == "INT") ||
                                          (fee.arr == "*" && fee.dep == dep) || (fee.arr == arr && fee.dep == "*")) &&
                                          fee.feetypeid == fty
                                          orderby fee.seq
                                          select fee;
                    }
                }
            }

            if (checkFeeCharges.Count() == 0)
            {
                checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                  where fee.site_id == siteId && fee.country == country &&
                                  ((fee.arr == arr && fee.dep == dep) || (fee.arr == "INT" && fee.dep == "INT") ||
                                  (fee.arr == "*" && fee.dep == dep) || (fee.arr == arr && fee.dep == "*")) &&
                                  fee.feetypeid == fty
                                  orderby fee.seq
                                  select fee;
            }

查询执行需要一段时间才能完成,不知道如何优化此查询。

返回json请求

if (checkFeeCharges.Any())
            {
                List<FeeAndChargesModel_Fee_Schedule> feeTable = new List<FeeAndChargesModel_Fee_Schedule>();
                foreach (var p in checkFeeCharges)
                {
                    feeTable.Add(
                        new FeeAndChargesModel_Fee_Schedule()
                        {
                            arr = FlightScheduleAPIController.GetCountryName(arr, siteId),
                            dep = FlightScheduleAPIController.GetCountryName(dep, siteId), 
                            country = p.country,
                            feedesc = p.feedesc,
                            feetype = p.feetype,
                            currency = p.currency,
                            value = p.value,
                            remark = p.remark
                        }
                    );
                    label = p.feetype;


                }

                mainJson.Add(
                        new FeeAndChargesModel_Main
                        {
                            label = label,
                            con_flight = FlightScheduleAPIController.GetCountryName(GetConnectingFlight(dep, arr), siteId),
                            details = feeTable
                        }
                        );
            }
        }

        return mainJson;

2 个答案:

答案 0 :(得分:1)

好的,所以这段代码真的很难阅读,但我们可以给你一些建议。

首先我注意到第一个sql语句被执行

var checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                              where fee.arr == arr && fee.dep == dep && fee.feetypeid == fty && fee.site_id == siteId
                              orderby fee.seq
                              select fee;

如果没有返回任何内容

        if (checkFeeCharges.Count() == 0)
        {

它执行的sql查询比第一个查询更具体。它具有所有相同的AND语句+另一个。如果第一个查询没有返回任何内容,那么期望(所有事物不变)应该是第二个不返回任何内容。如果是这样,为什么呢?

            checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                              where fee.arr == arr && fee.dep == dep && fee.feetypeid == fty && fee.site_id == siteId
                              && fee.country == country
                              orderby fee.seq
                              select fee;
        }

我个人会尝试理解或解决以下问题

1 预期的结果集大小是多少,我可以检索“少量”记录并在内存中处理这些记录。我需要了解结果集是否会随着时间的推移而增长,以及它的最小,最大类型边界。

2 是否有更好的数据库结构,我可以重构使用的代码,这将使这个查询更容易和更有效。

第3 为了实际能够优化这个查询,我会尝试直接在sql中编写它,并使用explain来帮助理解sql数据库正在做什么,正在使用什么索引以及返回结果集的大小每个查询。

。我也相信你应该能够将你所拥有的大量查询合并到一个表达式中。

这可能不完全正确,但作为演示应该没问题

from fee in dbDataContext.tbl_fee_schedules
where (fee.arr == arr && fee.dep == dep && fee.feetypeid == fty && fee.site_id == siteId
    && fee.country == country) || (fee.site_id == siteId && fee.country == country &&
                                              ((fee.arr == "AAX" && fee.dep == "AAX") || (fee.arr == "*" && fee.dep == dep) ||
                                              (fee.arr == arr && fee.dep == "*")) && fee.feetypeid == fty)
|| ( ..... ) | ( .... )

从我在那里可以看到你需要一些连接或子选择,这就是为什么在sql中尝试它会最快。还有一些linq2sql / ORM分析工具可能有助于诊断。

答案 1 :(得分:0)

很难说如何优化它,因为你在这里有很多重复。我开始尝试减少它。

要改变的一个显而易见的事情是:

if (checkFeeCharges.Count() == 0)

每次调用它时都会枚举整个查询。检查同样事情的便宜得多的方式:

if (!checkFeeCharges.Any())

这只会枚举查询中的一个结果,以确定它是否为空。