Filtravimas su Linq

įvertino 0 Atsakyta (Patvirtinta) Ši žinutė turi 1 patvitintas atsakymas | 6 Atsakymai | 2 Šalininkai

Top 10 autorių
Moteris
4 Žinutės
Taškai 95
Asta parašyta 08-27-2009 21:52

Sveiki,

Reiktu patarimo kaip geriau viena varianta issukti (galva nebenesa).

Turiu viena lenta, kuri turi sarysius su nemazai kitu lentu. Duomenys isvedami i GridView (na tas ne tiek svarbu). Reikia padaryti filtravima pagal viena ar kelis is tu lauku.


 protected void filterBtn_Click(object sender, EventArgs e)
    {
        DataBaseDataContext db = new DataBaseDataContext();

        IEnumerable<RiskRegister> q = from p in db.RiskRegisters select p;


      
        //DataControlFieldCollection col = GridView1.Columns;
       
        if (SortNumericddl.SelectedIndex != 0)
        {
            if (q.Count() != 0)
            //q = from p in q where p.Id == int.Parse(SortNumericddl.SelectedValue) select p;
            q= q.Where(p => p.Id == int.Parse(SortNumericddl.SelectedValue));
        }
        if (SortDamageType.SelectedIndex != 0)
        {
            if (q.Count()!=0)
            q = from p in q where p.DamageTypeId == int.Parse(SortDamageType.SelectedValue) select p;
        }
        if (SortRiskReason.SelectedIndex != 0)
        {
            if (q.Count() != 0)
            q = from p in q where p.RiskReasonTypeId == int.Parse(SortRiskReason.SelectedValue) select p;
        }
        if (SortRiskControlStatus.SelectedIndex != 0)
        {
            if (q.Count() != 0)
            q = from p in q where p.RiskControlStatusId == int.Parse(SortRiskControlStatus.SelectedValue) select p;
        }
        if (SortRiskResponseStatus.SelectedIndex != 0)
        {
            if (q.Count() != 0)
              
                q = from p in q where p.RiskResponseStatusId == int.Parse(SortRiskResponseStatus.SelectedValue) select p;
        }
        if (SortRiskTutor.SelectedIndex != 0)
        {
            if (q.Count() != 0)
                q = from p in q where p.RiskTutor == int.Parse(SortRiskTutor.SelectedValue) select p;
        }
        if (SortRiskMasterName.SelectedIndex != 0)
        {
            if (q.Count() != 0)
                q = from p in q where p.RiskCompanyId == int.Parse(SortRiskMasterName.SelectedValue) select p;
        }
        if (SortRiskMasterName.SelectedIndex != 0)
        {
            if (q.Count() != 0)
                q = from p in q where p.RiskCompanyId == int.Parse(SortRiskMasterName.SelectedValue) select p;
        }
        if (SortRiskChance.SelectedIndex != 0)
        {
            if (q.Count() != 0)
                q = from p in q where p.RiskChanceId == int.Parse(SortRiskChance.SelectedValue) select p;
        }
        if (SortRiskResultName.SelectedIndex != 0)
        {
            if (q.Count() != 0)
                q = from p in q where p.RiskResultId == int.Parse(SortRiskResultName.SelectedValue) select p;
        }
        if (SortRiskTotalName.SelectedIndex != 0)
        {
            if (q.Count() != 0)
                q = from p in q where p.RiskTotalTypeId == int.Parse(SortRiskTotalName.SelectedValue) select p;
        }
        if (SortRiskServiceName.SelectedIndex != 0)
        {
            if (q.Count() != 0)
                q = from p in q where p.RiskServiceId == int.Parse(SortRiskServiceName.SelectedValue) select p;
        }
       
        if (q.Count() > 0)
        {
            int mm = q.Count();
            /*var t = from m in q select new{

                RiskChanceName = m.RiskChance.Name,
                m.DateCreated,
                m.Updated,
                m.TargetUpdated,
                m.Id,
                m.Description,
                m.DateShowDate,
                m.DateDetect,
                m.Summary,
                informed = m.RiskInformedUser + "(" + m.RiskInformedDep + ")",
                DamageTypeName = m.DamageType.Name,
                RiskReasonName = m.RiskReasonType.Name,
                RiskControlStatusName = m.RiskControlStatus.Name,
                RiskResponseStatusName = m.RiskResponseStatus.Name,
                m.RiskFormFillUser,
                RiskTutor = m.SystemUser.Name_Surname,
                RiskMasterName = m.RiskCompanyFullView.Name,
                m.RiskResultDescription,
                m.RiskPriseDamage,
                RiskResultName = m.RiskResult.Name,
                RiskTotalName = m.RiskTotalType.Name,
                m.RiskReason,
                m.RiskAdministrateSolution,
                m.RiskNote,
                m.RiskMaster,
                m.RegulatoryMaster,
                m.tblRegulatorDoer,
                RiskServiceName = m.RiskService.Name,                
                m.WorkTime,
                link = "~/NoticeEditor.aspx?notice=" + m.Md5ash,
                           
           };*/
            GridView3.Visible = true;
            GridView3.DataSource = q;
            GridView3.DataBind();
        }
        else
        {
            GridView3.Visible = false;
        }


        db.Dispose();    
         
    }

 

SelectedIndex != 0 , tai tikrinu ar nera pirminis elementas, kurio value 0.

Viskas atrodytu kaip ir gerai (o gal galima su Linq kaip nors sujungt i viena tas uzklausas, cia greciausias variantas kuris man atejo i galva), bet jei as bandau paimti select new {} tai ant sitos vietos gaunu errorá - object reference is set null object ar pns.  Kas idomiausia, kad lygiai tokiu pat principu (tik nefiltruojant) isvedu i kita grid'a duomenis - viskas tvarkoje. Ar gali kad tokiu mano budu filtruojant kazkur sarysiai dingsta? O gal kur klaida ivelta, gal kas geriau pastebit nei as :)

 

Is anksto aciu uz patarimus

  • | Žinučių taškai: 35

Atsakyta (Patvirtinta) Patvitintas atsakymas

Top 10 autorių
Vyras
53 Žinutės
Taškai 1,080
Verified by Asta

DataBaseDataContext db = new DataBaseDataContext();
IEnumerable<RiskRegister> q = from p in db.RiskRegisters select p;     
if (SortNumericddl.SelectedIndex != 0)
{
  if (q.Count() != 0)
  q= q.Where(p => p.Id == int.Parse(SortNumericddl.SelectedValue));
}

Jau čia matau dvi dideles problemas:

Jeigu nori užklausai pritaikyti filtrą - reikėtų grąžinti IQueryable<T>, bet ne IEnumerable.

Kita problema - q.Count() != 0 - NE! Kada tu darai Count(), tavo LINQ to SQL užklausa bus materelizuota, t.y. įvyks SELECT COUNT(*) FROM X. Visi sekantys veiksmai jau bus atliekami su gautais objektais atmintyje. Natūralu, kad taip neturi būti. Pirma reikia suformuoti filtrą su WHERE sąlygomis, o tik tada daryti ToList() ar Count(). Nematau prasmės kiekvieną kartą tikrtinti ar != 0.

Aš panašius filtravimus darau taip:

var q = from x in X select x;
if (a)
{
  q = q.Where(x => x.A == a);
}
if (b)
{
  q = q.Where(x => x.B == b);
}
return q.ToList();

Mintį tikriausiai pagavai ;) Rezultate q bus reikalingą užklausą su visomis WHERE sąlygomis.

  • | Žinučių taškai: 40

Visi atsakymai

Top 10 autorių
Vyras
53 Žinutės
Taškai 1,080
Verified by Asta

DataBaseDataContext db = new DataBaseDataContext();
IEnumerable<RiskRegister> q = from p in db.RiskRegisters select p;     
if (SortNumericddl.SelectedIndex != 0)
{
  if (q.Count() != 0)
  q= q.Where(p => p.Id == int.Parse(SortNumericddl.SelectedValue));
}

Jau čia matau dvi dideles problemas:

Jeigu nori užklausai pritaikyti filtrą - reikėtų grąžinti IQueryable<T>, bet ne IEnumerable.

Kita problema - q.Count() != 0 - NE! Kada tu darai Count(), tavo LINQ to SQL užklausa bus materelizuota, t.y. įvyks SELECT COUNT(*) FROM X. Visi sekantys veiksmai jau bus atliekami su gautais objektais atmintyje. Natūralu, kad taip neturi būti. Pirma reikia suformuoti filtrą su WHERE sąlygomis, o tik tada daryti ToList() ar Count(). Nematau prasmės kiekvieną kartą tikrtinti ar != 0.

Aš panašius filtravimus darau taip:

var q = from x in X select x;
if (a)
{
  q = q.Where(x => x.A == a);
}
if (b)
{
  q = q.Where(x => x.B == b);
}
return q.ToList();

Mintį tikriausiai pagavai ;) Rezultate q bus reikalingą užklausą su visomis WHERE sąlygomis.

  • | Žinučių taškai: 40
Top 10 autorių
Vyras
53 Žinutės
Taškai 1,080

Dar dėl NullReference, tikriausiai, nufiltruojant vienas iš tavo m.RiskTotalType.Name tampa tiesiog null (šiuo atveju RiskTotalType).

  • | Žinučių taškai: 5
Top 10 autorių
Moteris
4 Žinutės
Taškai 95

Labai ačiū , tikrai apie IQueryable<T> net nesusimasčiau, o Tu visiškai teisus.

O su Count() pabandysiu kažką sugalvot. O nėra tekę susidurt su kokiu nors Linq sąlygų sujungimu (if ar kažką panašaus neleidžia lyg, o Stored Proceduros nesinori naudot)? Ar tokio dalyko neina padaryt?

Kas dėl null tai įdomu tai, kad vienoj funkcijoj naudoju lygiai toki pat metodą (select new {}), su tais pačiais parametrais ir laukais. Iš tos pačios lentelės. Ir ten taip pat yra vietų kur kažkieno ID (iš saryšių) yra null, bet jokios klaidos neįvyksta.O gal iš tikro filtruojant kažką pametu :). Dėkui dar kartą , bandysiu patarimais pasinaudot ir  kažką išsukt :)

  • | Žinučių taškai: 20
Top 10 autorių
Vyras
53 Žinutės
Taškai 1,080

Gali patikslinti ką turi omeny "LINQ sąlygų apjungimu".

var q = from x in X select x;
if (a)
{
  q = q.Where(x => x.A == a);
}
if (b)
{
  q = q.Where(x => x.B == b);
}
return q.ToList();

Ar tai nėra apjungimas? Kol tu neįvykdysi ToList(), jokių užklausų į DB neina, o formuojamas WHERE A = a AND B = b (jeigu perduoti abu parametrai) arba WHERE B = b (jeigu perduotas tik b). Gali gal konkretesnį pvz pateikti, galėčiau gal geriau padėti.

  • | Žinučių taškai: 20
Top 10 autorių
Moteris
4 Žinutės
Taškai 95

Viskas gerai, problema issisprende vien pakeitus  IEnumerable i IQueryable. Labai dėkui :). O dėl sujungimo irgi viskas gerai, ne taip vakar į Tavo pranešimą pažiūrėjau. Dėl to sakoma - rytas už vakarą protingesnis :). Dar kartą dėkui ;)

  • | Žinučių taškai: 20
Top 10 autorių
Vyras
53 Žinutės
Taškai 1,080

Visada prašom :) Bus klausimų - drąsiai rašyk!

Puslapis 1 iš 1 (7) | RSS
DotNetGroup.LT, 2009
Sprendimas