2009-05-30 18 views
9

ho una query LINQ mappata con Entity Framework che sembra qualcosa di simile:LINQ - NON selezionare determinati campi?

image = this.Context.ImageSet 
        .Where(n => n.ImageId == imageId) 
        .Where(n => n.Albums.IsPublic == true) 
        .Single(); 

Questo restituisce un singolo oggetto dell'immagine e funziona come previsto.

Tuttavia, questa query restituisce tutte le proprietà della mia tabella Immagine nel DB. In circostanze normali, ciò andrebbe bene ma queste immagini contengono molti dati binari che richiedono molto tempo per essere restituiti.

In sostanza, in essa allo stato attuale la mia query LINQ sta facendo:

Select ImageId, Name, Data 
From Images 
... 

ma ho bisogno di una query che fa questo instread:

Select ImageId, Name 
From Images 
... 

Avviso voglio caricare tutto tranne il dati. (Posso ottenere questi dati su un secondo passaggio asincrono)

risposta

8

Sfortunatamente, se si utilizza LINQ to SQL, non esiste una soluzione ottimale.

avete 3 opzioni:

  1. ritorni l'Ente, con il monitoraggio di contesto e tutti, in questo caso Immagine, con tutti i campi
  2. si sceglie i vostri campi e restituire un tipo anonimo
  3. È scegli i tuoi campi e restituisci una classe personalizzata fortemente tipizzata, ma perdi il monitoraggio, se questo è ciò che desideri.

Amo LINQ to SQL, ma così è.

La mia unica soluzione per voi sarebbe quella di ristrutturare il DataBase e spostare tutti i dati di grandi dimensioni in una tabella separata e collegarli ad essa dalla tabella Immagine.

In questo modo quando si restituisce Image si restituisce solo una chiave nel nuovo campo DataID e quindi è possibile accedere a Dati più pesanti quando e se necessario.

applausi

+0

Penso che senza l'opzione di caricamento ritardato come LINQ to SQL, questa è la soluzione migliore per me. – vidalsasoon

+0

sì, penso che con LINQ a SQL a volte sia necessario modificare lo schema per adattarlo al modello. a volte si scopre che in realtà finisce per rendere il tuo DB design migliore ....? – andy

1

Ciò creerà una nuova immagine con solo quei campi impostati. Quando si torna indietro per ottenere i dati per le immagini selezionate, suggerirei di andare avanti e ottenere il set di dati completo invece di provare a unirlo con i dati id/nome esistenti. I campi id/name sono presumibilmente piccoli rispetto ai dati e il codice sarà molto più semplice di un tentativo di unione. Inoltre, potrebbe non essere necessario costruire effettivamente un oggetto Image, utilizzando un tipo anonimo potrebbe soddisfare i tuoi scopi altrettanto bene.

image = this.Context.ImageSet 
        .Where(n => n.ImageId == imageId) 
        .Where(n => n.Albums.IsPublic == true) 
        .Select(n => new Image { ImageId = n.ImageId, Name = n.Name } 
        .Single(); 
+1

Avevo pensato alla soluzione fornita ma la mia preoccupazione stava perdendo lo stato dell'entità da quando è stata creata una nuova immagine. Inoltre, il tipo restituito è "Immagine", quindi non penso che il tipo Anonimo sia possibile. Farò dei test con il – vidalsasoon

0

In alternativa è possibile utilizzare il select nuova nell'espressione di query ...

var image = 
(
    from i in db.ImageSet 
    where i.ImageId == imageId && i.Albums.IsPublic 
    select new 
    { 
     ImageId = i.ImageId, 
     Name = i.Name 
    } 
).Single() 

Le espressioni di query LINQ in realtà vengono convertiti per l'espressione lambda al momento della compilazione, ma io prefair utilizzando l'espressione di query generalmente perché lo trovo più leggibile e comprensibile.

Grazie :)

1

[Se utilizzando Linq 2 SQL] All'interno del progettista DBML, v'è la possibilità di fare ritardare-caricato colonne della tabella individuale. Impostare questo su true per il tuo campo binario di grandi dimensioni. Quindi, tali dati non vengono caricati fino a quando non vengono effettivamente utilizzati.

[Domanda per tutti voi: qualcuno sa se i framework di entità supportano varbinary/varchar caricati in ritardo in MSVS 2010? ]

Soluzione # 2 (per strutture a entità o LINQ 2 SQL):

creare una vista della tabella che include solo la chiave primaria e il varchar (max)/varbinary (max). Mappalo in EF.

All'interno della finestra di progettazione Entity Framework, eliminare la proprietà varbinary (max)/varchar (max) dalla definizione della tabella (lasciandola definita solo nella vista). Questo dovrebbe escludere il campo dalle operazioni di lettura/scrittura a quella tabella, sebbene sia possibile verificarlo con il registratore.

Generalmente si accede ai dati tramite la tabella che esclude il blob di dati. Quando hai bisogno del blob, carichi una riga dalla vista. Non sono sicuro che se sarai in grado di scrivere alla vista, non sono sicuro di come faresti le scritture. Potresti essere in grado di scrivere sulla vista, o potresti aver bisogno di scrivere una stored procedure, oppure puoi scomporre un file DBML per la stessa tabella.

+0

Penso che questo sia solo per LINQ to SQL? Peccato. sarebbe stato perfetto – vidalsasoon

+0

Oops si, questo può essere solo per linq 2 sql. –

+0

[Domanda per tutti voi: qualcuno sa se i framework di entità supportano varbinary/varchar caricati in ritardo in MSVS 2010? ] RISPOSTA: NO :( – vidalsasoon

1

Non puoi farlo con LINQ almeno per ora ...

L'approccio migliore che conosco è creare View per la tabella è necessario, senza grandi campi e utilizzare LINQ con quello View.

+1

sì, è solo andata! Ho provato a selezionare alcuni campi con classe personalizzata, ma il problema rimane un campo nvarchar (max) con xmlFile non è in non nel selezionare ma crash con Errore nell'esecuzione di richiesta figlio per gestore 'System.Web.Mvc.HttpHandlerUtil + ServerExecuteHttpHandlerAsyncWrapper'. Ho usato la vista senza file di grandi dimensioni e funziona! – Evilripper

Problemi correlati