Linq查询头痛

时间:2012-11-20 10:36:28

标签: sql linq entity-framework

对于项目,我们必须使用具有Entity框架的现有表。这解决了搜索功能的1个大linq查询。目前,此功能需要3秒才能获得10个结果。

问题是,是否有人知道要改进这个linq?

这是linq查询:

var result = (from o in db.Objects
                                  join omsc in db.Omschrijvingen on o.Omschrijving_Identifier equals omsc.Identifier
                                  join a in db.Adressen on o.Adres_Id equals a.Adres_Id
                                  join oa in db.Object_Abonnement on o.Object_Id equals oa.Object_ID
                                  join oaf in db.Object_Afbeeldingen on o.Object_Id equals oaf.Object_Id
                                  where o.Enabled && oaf.StandaardAfbeelding == true &&
                                        (!iType.Any() || iType.Contains(o.Type_Id)) &&
                                        (iProvince < 1 || a.Provincie_Id == iProvince) &&
                                        (iDepartement < 1 || a.Departement_Id == iDepartement) &&
                                        o.Object_Logs.All(
                                            ol => ol.Log_Type != (int) ApplicationDefinitions.LogTypes.Deleted) &&
                                        (oa.Betaald && oa.Tot >= DateTime.Now) &&
                                        (!kenmerken.Any() ||
                                         db.Object_Kenmerken.Count(
                                             ken =>
                                             kenmerken.Contains(ken.Kenmerk_Id) && ken.Object_Id == o.Object_Id &&
                                             ken.Waarde.ToUpper() != "FALSE" && ken.Waarde != "0") == kenmerken.Count()) &&
                                        (search.Length < 1 || omsc.Naam.ToLower().Contains(search.ToLower()) ||
                                         omsc.Omschrijving.ToLower().Contains(search.ToLower()) ||
                                         a.Woonplaats.ToLower().Contains(search.ToLower()))
                                  select new FullObject
                                             {
                                                 Object_Id = o.Object_Id,
                                                 Adres_Id = a.Adres_Id,
                                                 DepartmentId = a.Departement_Id,
                                                 Department = (a.Departementen != null) ? a.Departementen.Naam : "",
                                                 ProviciesId = a.Provincie_Id,
                                                 Provicie = (a.Provicies != null) ? a.Provicies.Naam : "",
                                                 Contact_Id = o.Contact_Id,
                                                 Naam = omsc.Naam,
                                                 Omschrijving = omsc.Omschrijving,
                                                 Prijs =
                                                     (((db.Prijs_Periode.Where(pp => pp.Object_Id == o.Object_Id).Min(
                                                         pp => pp.Prijs_Dag) > 0)
                                                           ? db.Prijs_Periode.Where(pp => pp.Object_Id == o.Object_Id).
                                                                 Min(pp => pp.Prijs_Dag)
                                                           : db.Prijs_Periode.Where(pp => pp.Object_Id == o.Object_Id).
                                                                 Min(pp => pp.Prijs_Week)) > 0)
                                                         ? (db.Prijs_Periode.Where(pp => pp.Object_Id == o.Object_Id).
                                                                Min
                                                                (pp => pp.Prijs_Dag) > 0)
                                                               ? db.Prijs_Periode
                                                                     .Where(
                                                                         pp => pp.Object_Id == o.Object_Id)
                                                                     .Min(pp => pp.Prijs_Dag)
                                                               : db.Prijs_Periode
                                                                     .Where(
                                                                         pp => pp.Object_Id == o.Object_Id)
                                                                     .Min(pp => pp.Prijs_Week/7)
                                                         : (db.Prijs_Periode
                                                                .Where(pp => pp.Object_Id == o.Object_Id)
                                                                .Min(pp => pp.Prijs_Weekend) > 0)
                                                               ? db.Prijs_Periode
                                                                     .Where(
                                                                         pp => pp.Object_Id == o.Object_Id)
                                                                     .Min(pp => pp.Prijs_Weekend/3)
                                                               : (db.Prijs_Periode
                                                                      .Where(
                                                                          pp => pp.Object_Id == o.Object_Id)
                                                                      .Min(pp => pp.Prijs_Midweek) > 0)
                                                                     ? db.Prijs_Periode
                                                                           .Where(
                                                                               pp =>
                                                                               pp.Object_Id == o.Object_Id)
                                                                           .Min(pp => pp.Prijs_Midweek/14)
                                                                     : (db.Prijs_Periode
                                                                            .Where(
                                                                                pp =>
                                                                                pp.Object_Id == o.Object_Id)
                                                                            .Min(pp => pp.Prijs_Langweekend) >
                                                                        0)
                                                                           ? db.Prijs_Periode
                                                                                 .Where(
                                                                                     pp =>
                                                                                     pp.Object_Id == o.Object_Id)
                                                                                 .Min(
                                                                                     pp =>
                                                                                     pp.Prijs_Langweekend)
                                                                           : 0,
                                                 SPrijs = (((db.Prijs_Periode
                                                                 .Where(
                                                                     pp =>
                                                                     pp.Object_Id == o.Object_Id &&
                                                                     pp.Aanbieding == false)
                                                                 .Min(pp => pp.Prijs_Dag) > 0)
                                                                ? db.Prijs_Periode
                                                                      .Where(
                                                                          pp =>
                                                                          pp.Object_Id == o.Object_Id &&
                                                                          pp.Aanbieding == false)
                                                                      .Min(pp => pp.Prijs_Dag)
                                                                : db.Prijs_Periode
                                                                      .Where(
                                                                          pp =>
                                                                          pp.Object_Id == o.Object_Id &&
                                                                          pp.Aanbieding == false)
                                                                      .Min(pp => pp.Prijs_Week)) > 0)
                                                              ? (db.Prijs_Periode
                                                                     .Where(
                                                                         pp =>
                                                                         pp.Object_Id == o.Object_Id &&
                                                                         pp.Aanbieding == false)
                                                                     .Min(pp => pp.Prijs_Dag) > 0)
                                                                    ? db.Prijs_Periode
                                                                          .Where(
                                                                              pp =>
                                                                              pp.Object_Id == o.Object_Id &&
                                                                              pp.Aanbieding == false)
                                                                          .Min(pp => pp.Prijs_Dag)
                                                                    : db.Prijs_Periode
                                                                          .Where(
                                                                              pp =>
                                                                              pp.Object_Id == o.Object_Id &&
                                                                              pp.Aanbieding == false)
                                                                          .Min(pp => pp.Prijs_Week/7)
                                                              : (db.Prijs_Periode
                                                                     .Where(
                                                                         pp =>
                                                                         pp.Object_Id == o.Object_Id &&
                                                                         pp.Aanbieding == false)
                                                                     .Min(pp => pp.Prijs_Weekend) > 0)
                                                                    ? db.Prijs_Periode
                                                                          .Where(
                                                                              pp =>
                                                                              pp.Object_Id == o.Object_Id &&
                                                                              pp.Aanbieding == false)
                                                                          .Min(pp => pp.Prijs_Weekend/3)
                                                                    : (db.Prijs_Periode
                                                                           .Where(
                                                                               pp =>
                                                                               pp.Object_Id == o.Object_Id &&
                                                                               pp.Aanbieding == false)
                                                                           .Min(pp => pp.Prijs_Midweek) > 0)
                                                                          ? db.Prijs_Periode
                                                                                .Where(
                                                                                    pp =>
                                                                                    pp.Object_Id == o.Object_Id &&
                                                                                    pp.Aanbieding == false)
                                                                                .Min(pp => pp.Prijs_Midweek/14)
                                                                          : (db.Prijs_Periode
                                                                                 .Where(
                                                                                     pp =>
                                                                                     pp.Object_Id == o.Object_Id &&
                                                                                     pp.Aanbieding == false)
                                                                                 .Min(pp => pp.Prijs_Langweekend) >
                                                                             0)
                                                                                ? db.Prijs_Periode
                                                                                      .Where(
                                                                                          pp =>
                                                                                          pp.Object_Id == o.Object_Id &&
                                                                                          pp.Aanbieding == false)
                                                                                      .Min(
                                                                                          pp =>
                                                                                          pp.Prijs_Langweekend)
                                                                                : 0,
                                                 Personen =
                                                     (db.Object_Kenmerken.Any(
                                                         iok =>
                                                         iok.Kenmerk_Id == iAantalPersonenId &&
                                                         iok.Object_Id == o.Object_Id))
                                                         ? db.Object_Kenmerken.Where(
                                                             iok =>
                                                             iok.Kenmerk_Id == iAantalPersonenId &&
                                                             iok.Object_Id == o.Object_Id).Select(
                                                                 iok => EntitiesFunctions.ParseInt(iok.Waarde)).
                                                               FirstOrDefault()
                                                         : 0,
                                                 Slaapkamers =
                                                     (db.Object_Kenmerken.Any(
                                                         iok =>
                                                         iok.Kenmerk_Id == iAantalSlaapkamersId &&
                                                         iok.Object_Id == o.Object_Id))
                                                         ? db.Object_Kenmerken.Where(
                                                             iok =>
                                                             iok.Kenmerk_Id == iAantalSlaapkamersId &&
                                                             iok.Object_Id == o.Object_Id).Select(
                                                                 iok => EntitiesFunctions.ParseInt(iok.Waarde)).
                                                               FirstOrDefault()
                                                         : 0,
                                                 UrlKey = omsc.UrlKey,
                                                 Title = omsc.Title,
                                                 Plaats = a.Woonplaats,
                                                 Enabled = o.Enabled,
                                                 GoogleMap_Url = o.GoogleMap_Url,
                                                 InkoopPrijs = o.InkoopPrijs,
                                                 Type_Id = o.Type_Id,
                                                 Website = o.Website,
                                                 Adressen = o.Adressen,
                                                 Thumb = oaf.Tumbnial
                                             }
                                 )
                    .Where(item => (item.Prijs >= minPrice || minPrice == 0) &&
                                   (item.Prijs <= maxPrice || maxPrice == 0) &&
                                   (bOffersOnly == false || item.Prijs < item.SPrijs) &&
                                   (item.Personen >= personen || personen == 0) &&
                                   (item.Slaapkamers == slaapkamers || slaapkamers == 0))
                    .Distinct();

更清楚:

我们需要获得以下对象:

public class FullObject
        {
            public int Object_Id { get; set; }
            public int? Adres_Id { get; set; }
            public int Contact_Id { get; set; }
            public string Naam { get; set; }
            public string Omschrijving { get; set; }
            public decimal? Prijs { get; set; }
            public decimal? SPrijs { get; set; }
            public int Personen { get; set; }
            public int Slaapkamers { get; set; }
            public string UrlKey { get; set; }
            public string Title { get; set; }
            public string Plaats { get; set; }
            public int ProviciesId { get; set; }
            public string Provicie { get; set; }
            public int? DepartmentId { get; set; }
            public string Department { get; set; }
            public bool Enabled { get; set; }
            public string GoogleMap_Url { get; set; }
            public decimal? InkoopPrijs { get; set; }
            public int Type_Id { get; set; }
            public string Website { get; set; }
            public List<Data.Object_Kenmerken> ItemKenmerken { get; set; }
            public Data.Adressen Adressen { get; set; }
            public string Thumb { get; set; }
        }

我们必须过滤以下内容

int[] iType
string search
int[] kenmerken
int iProvince
int iDepartement
decimal minPrice
decimal maxPrice
int personen
int slaapkamers
bool bOffersOnly

这是(一点点)表结构:

http://i.stack.imgur.com/3Y0Tf.jpg

我们试图单独获取所有内容,但随后我们总共获得了12秒(并且还在增长),因为数据库中存在许多对象,然后我们需要通过过滤来获取它们。

我希望有人认为这是一个挑战,看到我忽略的东西。

提前致谢。

克里斯蒂安

由于此故障单已关闭,我的回答是:

感谢所有回复。

最好的是来自@ Daniel-Hilgarth的人。不将计算放在查询中。修复我们选择在每15分钟运行一次的SQL作业中进行计算并将结果直接放在Object表中。

接下来我们将连接更改为数据库逻辑。感谢@ Micheal-Samteladze。

所有这些更改都会给我们以下查询。

var result = (from o in db.Objects
                join omsc in db.Omschrijvingen on o.Omschrijving_Identifier equals omsc.Identifier
                where o.Enabled &&
                    (!iType.Any() || iType.Contains(o.Type_Id)) &&
                    (o.Prijs >= minPrice || minPrice == 0) &&
                    (o.Prijs <= maxPrice || maxPrice == 0) &&
                    (bOffersOnly == false || o.Prijs < o.SPrijs) &&
                    (o.Personen >= personen || personen == 0) &&
                    (o.Kamers == slaapkamers || slaapkamers == 0) &&
                    (iProvince < 1 || o.Adressen.Provincie_Id == iProvince) &&
                    (iDepartement < 1 || o.Adressen.Departement_Id == iDepartement) &&
                    o.Object_Logs.All(ol => ol.Log_Type != (int) ApplicationDefinitions.LogTypes.Deleted) &&
                    o.Object_Abonnement.Any(oa => oa.Betaald && oa.Tot >= DateTime.Now) &&
                    (!kenmerken.Any() || o.Object_Kenmerken.Count(ken => kenmerken.Contains(ken.Kenmerk_Id) && ken.Object_Id == o.Object_Id && ken.Waarde.ToUpper() != "FALSE" && ken.Waarde != "0") == kenmerken.Count()) &&
                    (search.Length < 1 || omsc.Naam.ToLower().Contains(search.ToLower()) || omsc.Omschrijving.ToLower().Contains(search.ToLower()) || o.Adressen.Woonplaats.ToLower().Contains(search.ToLower()))
                select new FullObject
                {
                    Object_Id = o.Object_Id,
                    Adres_Id = o.Adressen.Adres_Id,
                    DepartmentId = o.Adressen.Departement_Id,
                    Department = (o.Adressen.Departementen != null) ? o.Adressen.Departementen.Naam : "",
                    ProviciesId = o.Adressen.Provincie_Id,
                    Provicie = (o.Adressen.Provicies != null) ? o.Adressen.Provicies.Naam : "",
                    Contact_Id = o.Contact_Id,
                    Naam = omsc.Naam,
                    Omschrijving = omsc.Omschrijving,
                    Prijs = o.Prijs ?? 0,
                    SPrijs = o.SPrijs ?? 0,
                    Personen = o.Personen,
                    Slaapkamers = 0,
                    UrlKey = omsc.UrlKey,
                    Title = omsc.Title,
                    Plaats = o.Adressen.Woonplaats,
                    Enabled = o.Enabled,
                    GoogleMap_Url = o.GoogleMap_Url,
                    InkoopPrijs = o.InkoopPrijs,
                    Type_Id = o.Type_Id,
                    Website = o.Website,
                    Adressen = o.Adressen,
                    Thumb = o.Object_Afbeeldingen.FirstOrDefault(af => af.StandaardAfbeelding).Tumbnial
                }
            ) 
.Distinct();

这需要大约1秒半的时间来给出前10个结果,而旧的结果至少要达到3个。

但我仍然愿意接受建议。

由于

克里斯蒂安

1 个答案:

答案 0 :(得分:0)

当我查看您的查询时,我可以发现您正在查询查询中的数据库对象。

如果你在数据库中推送你的逻辑并在LINQ中得到结果,它会快得多。