277 messaggi dal 03 ottobre 2006
grazie Alessio, non c'è dubbio che io debba studiare ancora molto dato che è il primo progetto che provo a fare con Linq To Entities ed Entity Framework quindi andrò a guardare i link che mi hai passato.

Per la cronaca, ho applicato i tuoi suggerimenti anche perchè ho capito la filosofia del cambiamento che mi hai chiesto di fare ed ora funziona correttamente anche ho dovuto comunque sostituire ToList() nelle due query con AsEnumerable() altrimenti la Union non la faceva dato che le due query in realtà proiettano i dati su una stessa DTO ma non ti avevo detto che pescano i dati da due entità diverse.

Poi ho notato che non ti avevo risposto sul passaggio di una dropdownlist come parametro... in realtà per ora l'ho fatto per "fretta" nel senso che poi lo cambierò passando solo la lista di elementi variabili da cui è composta
333 messaggi dal 05 novembre 2012
grazie Alessio, non c'è dubbio che io debba studiare ancora molto dato che è il primo progetto che provo a fare con Linq To Entities ed Entity Framework quindi andrò a guardare i link che mi hai passato.



Per la cronaca, ho applicato i tuoi suggerimenti anche perchè ho capito la filosofia del cambiamento che mi hai chiesto di fare ed ora funziona correttamente anche ho dovuto comunque sostituire ToList() nelle due query con AsEnumerable() altrimenti la Union non la faceva dato che le due query in realtà proiettano i dati su una stessa DTO ma non ti avevo detto che pescano i dati da due entità diverse.

a quale ToList() ti stai riferendo?

ma non ti avevo detto che pescano i dati da due entità diverse

non importa, quello che deve coincidere è la struttura finale, nel tuo caso BarcaplanningDTO

Poi ho notato che non ti avevo risposto sul passaggio di una dropdownlist come parametro... in realtà per ora l'ho fatto per "fretta" nel senso che poi lo cambierò passando solo la lista di elementi variabili da cui è composta

Non è fretta è cattiva abitudine :)
Stratificare il tuo applicativo è sicuramente una buona cosa, ne guadagni in leggibilità e manutenzione ma attenzione a non abusarne e come gestisci i diversi strati e le responsabilità...per es. nel caso specifico, GetBarchePlanningDTO è un metodo che fa parte dello strato che si occupa di recuperare i dati dal database, utilizzare qui l'oggetto DropDownList (che fa parte del namespace System.Web.UI.WebControls) significa aggiungere a questo strato una dipendenza ad un oggetto che lavora a livello di interfaccia

UPDATE: ho dato una riletta veloce ai post per capire meglio, la union complica lo scenario e mi sà che per la tua esigenza una query linq non basta, più tardi se ho tempo riguardo meglio

/Ciao
Modificato da scioCoder il 20 marzo 2019 13:45 -

Alessio
277 messaggi dal 03 ottobre 2006
Se proprio vuoi aiutarmi ti mostro la versione completa "funzionante" ma sicuramente migliorabile...
Ecco le considerazioni:
query, quer1 e query2 sono di fatto insiemi disgiunti quindi se non ho capito male potrei usare anche Concat invece di Union per unirli nella query3 finale
query pesca da un entità contenente barche sicuramente non presenti in query1
query2 "dovrebbe" pescare dall'entità che contiene TUTTE le barche togliendo quelle presenti in query e query1. Per fare questo uso le due liste IList0 e 1 per ricavare l'id delle barche delle prime due query e toglierli nella query2 anche se sono certo esistano metodi migliori solo che non li trovo...
Infine AsEnumerable alla fine delle 3 query ho dovuto metterlo altrimenti la Union mi da errore (ho letto che da errore perchè anche se le query creano tutte lo stesso DTO pescano dati da entità diverse.


public IQueryable<BarcaplanningDTO> GetBarchePlanningDTO(ListItemCollection ddl, int mese, int anno, string tipofiltro)
{
List<int> IdList0 = null;
List<int> IdList1 = null;
List<Filter> filtro = new List<Filter>();
Func<BarcaplanningDTO, bool> deleg = null;

if (ddl.Count > 0)
{
foreach (ListItem t in ddl)
{
filtro.Add(new Filter { PropertyName = t.Text, Operation = (tipofiltro == "") ? Op.Equals : Op.Contains, Value = t.Value });
}
deleg = FiltroExpressionBuilder.GetExpression<BarcaplanningDTO>(filtro).Compile();
}

var query = _db.ListEventiBarche
.Where(r => r.Evento.Event_date.Month == mese || r.Evento.Event_end_date.Month == mese)
.GroupBy(r => r.Barca.BarcaID)
.Select(r => new BarcaplanningDTO
{
BarcaID = r.Key,
EventoExtraID = r.Select(x => 0).ToList(),
Titolo = r.Select(x => x.Evento.Title).ToList(),
Modello = r.Select(x => x.Barca.Modello).FirstOrDefault(),
Nome = r.Select(x => x.Barca.Nome).FirstOrDefault(),
Regione = r.Select(x => x.Barca.Regione).FirstOrDefault(),
Letti = r.Select(x => x.Barca.Letti).FirstOrDefault(),
Imbarco = r.Select(x => x.Imbarco.Nome).ToList(),
Occupata = r.Select(x => 3).ToList(),
Ordine = 3,
Dateint = r.Select(x => new Intervallodate { EventoID = x.EventoID, Event_date = x.Evento.Event_date, Event_end_date = x.Evento.Event_end_date }).ToList()
}).AsEnumerable();


var query1 = _db.ListEventiExtraBarche
.Where(r => r.Event_date.Month == mese || r.Event_end_date.Month == mese)
.GroupBy(r => r.Barca.BarcaID)
.Select(r => new BarcaplanningDTO
{
BarcaID = r.Key,
EventoExtraID = r.Select(x => x.EventoExtraID).ToList(),
Titolo = r.Select(x => x.Title).ToList(),
Modello = r.Select(x => x.Barca.Modello).FirstOrDefault(),
Nome = r.Select(x => x.Barca.Nome).FirstOrDefault(),
Regione = r.Select(x => x.Barca.Regione).FirstOrDefault(),
Letti = r.Select(x => x.Barca.Letti).FirstOrDefault(),
Imbarco = r.Select(x => "").ToList(),
Occupata = r.Select(x => x.Occupata).ToList(),
Ordine = 2,
Dateint = r.Select(x => new Intervallodate { EventoID = x.EventoExtraID, Event_date = x.Event_date, Event_end_date = x.Event_end_date }).ToList()
}).AsEnumerable();

IdList0 = query.Select(r => r.BarcaID).ToList();
IdList1 = query1.Select(t => t.BarcaID).ToList();
foreach (int li in IdList1)
IdList0.Add(li);


var query2 = _db.ListBarche.Where(p => !IdList0.Any(p2 => p2 == p.BarcaID))
.Select(r => new BarcaplanningDTO
{
BarcaID = r.BarcaID,
Modello = r.Modello,
Nome = r.Nome,
Letti = r.Letti,
Regione = r.Regione,
Imbarco = new List<string> { "" }.ToList(),
Ordine = 0,
Occupata = new List<int> { 0 }.ToList(),
}).AsEnumerable();

var query3 = query.Union(query1).Union(query2).AsQueryable();

if (filtro.Count > 0)
return query3.Where<BarcaplanningDTO>(deleg).AsQueryable();
else
return query3;
}


public class BarcaplanningDTO
{

[DefaultValue(0)]
public List<int> EventoExtraID { get; set; }
public int BarcaID { get; set; }
public List<Intervallodate> Dateint { get; set; }
public List<string> Titolo { get; set; }
public string Modello { get; set; }
public string Nome { get; set; }
public int Letti { get; set; }
public string Regione { get; set; }
[DefaultValue("")]
public List<string> Imbarco { get; set; }
public string Imbarcostring
{
get { return string.Join(",", Imbarco); }
set { Imbarcostring = value; }
}
[DefaultValue(0)]
public List<int> Occupata { get; set; }
public int Ordine { get; set; }
}
333 messaggi dal 05 novembre 2012
Ciao wmartin,

Se proprio vuoi aiutarmi ti mostro la versione completa "funzionante" ma sicuramente migliorabile..


la vera questione non è aiutarti ma che tu capisca quello che fai e da quel che vedo non hai capito un granchè...la mia impressione è che vai a tentativi e quando tutto viene compilato ed in qualche modo eseguito allora va bene

con molta probabilità non hai ancora capito come e quando la tua query viene eseguita, qualche post fa ti ho segnalato questo link, se non hai ancora letto e compreso ti consiglio di leggerlo prima di andare avanti, è un concetto fondamentale che devi capire bene per evitare di farti del male (e questo cmq in generale)
https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/ef/language-reference/query-execution

penso che non stai applicando il suggerimento (non solo mio) di verificare le query che vengono realmente eseguite a db, il codice che hai postato (tralasciando la logica) esegue un fracco di query

stai smanettando con l'albero di espressioni e preferisco evitare e sapere il perchè

Per correttezza...mi sono accorto di averti detto una cosa in parte sbagliata, la union (lo stesso vale anche per concat) non la puoi utilizzare per gestire il tuo caso, ef non è in grado di gestire la concatenazione di query annidate che contengono delle collection. Per farlo dovresti eseguire la concatenazione in memoria ma questo non ha alcun senso visto che il risultato deve essere visualizzato in una griglia paginata

Per questa esigenza in particolare (GetBarchePlanningDTO)...penso che linq to entities non sia la scelta giusta per ottenere il risultato desiderato, meglio affrontarla diversamente, per es. con una store procedure

In generale...quello che ti ho scritto è il mio pensiero giusto o sbagliato condivisibile o meno
Ti consiglio di fermarti un attimo e formarti un pochino meglio sull'argomento...ed antiticipo...giustificare tutto questo con la scusa della fretta non ha alcun valore...poi vedi tu

/Ciao

Alessio
277 messaggi dal 03 ottobre 2006
grazie lo stesso Alessio
confermo che i link che mi hai passato li ho letti ma non ancora "applicati" anche perchè prima vanno compresi bene, così come ho notato la quantità di query che vengono in realtà eseguite usando LinqPad4 come applicazione di test perche mi mostra subito come vengono trasformate le query in SQL
Io provengo da anni di utilizzo di ObjectDataSource e istruzioni SQL dirette al DB o all'uso di Stored Procedure così, provando ad "aggiornarmi" sulle novità informatiche, mi è parso all'inizio molto "comodo" l'utilizzo di Entity Framework e Linq To Entities perchè semplificano le righe di codice da scrivere ma ammetto che mi sono imputato sul voler usare queste strutture sempre e comunque cercando di ottimizzarle (quando capirò bene come si usano).

Dalle parole che scrivi e dalle query che vengono poi eseguite in questo particolare caso del GetBarchePlanningDTO mi sa che mi conviene davvero accettare di fare una query diretta al DB per evitare di "farmi male" magari quando i dati saranno più numerosi.
333 messaggi dal 05 novembre 2012
Secondo me c'è un errore di fondo e putroppo non sei l'unico ad operare in questo modo.
Se devo fare un progetto per lavoro e scegliere tra una tecnologia che conosco ed una più recente che non conosco ho due strade
1) ho tempo di formarmi su quella nuova, lo faccio e poi parto con il progetto
2) non ho tempo di formarmi, utilizzo la mia solita che conosco bene

Detto questo, ognuno è libero di fare le proprie scelte

Per tua conoscenza...utilizzare in un progetto entity framework non significa che per forza di cose devo fare tutto con linq...anzi
puoi utilizzare un approccio misto e l'addove non risulta fattibile con linq o servono particolari performance operare direttamente con codice sql (o store procedure) sfruttando comunque la funzionalità di mapping sulle tue classi. vedi Database.SqlQuery e Database.ExecuteSqlCommand

/Ciao

Alessio

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.