2015-06-24 58 views
10

!!! Si prega di non reindirizzare a this article, in quanto non risolve il problema descritto di seguito.LINQ2SQL: come modificare i valori dei campi durante il caricamento di entità anonime?

Diciamo che abbiamo una tale tabella nel database:

SomeTable

  • ID (int)
  • DT (datetime)

abbiamo configurato un data Linq2Sql contesto. E abbiamo configurato un'entità per SomeTable: Il metodo OnLoaded modifica DT in modo che DateTimeKind di DT diventi Utc (inizialmente non specificato).

Ora qui è il problema:

Se chiediamo dati utilizzando intera entità, il metodo OnLoaded si chiama:

From x In ourDataContext.SomeTable Select x 

Ma se si richiede solo una parte del tavolo (e quindi generare un anonimo tipo), l'OnLoaded non si chiama:

From x In ourDataContext.SomeTable Select x.DT 

è chiaro che OnLoaded è definita entità SomeTable, e non nel tipo anonimo.

Al momento considero la creazione di entità personalizzate che sostituiscono i tipi anonimi. Ma forse qualcuno ha una soluzione migliore?

risposta

1

Abbiamo avuto un problema simile a quello necessario per ricevere parte dei campi dall'entità come oggetto anonimo e sapere sempre che abbiamo DateTimeKind di campi data come DateTimeKind.UTC senza utilizzare funzioni aggiuntive nella richiesta LINQ.

Abbiamo provato un sacco di cose, ma abbiamo trovato solo una soluzione abbastanza buona - la generazione di codice per Linq2Sql con T4.

P.S. Se si desidera ottenere ulteriori informazioni sulla generazione del codice Linq2Sql con T4, è possibile iniziare da http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx

+0

Immagino che sia l'unico modo per ora ...: / – Dima

0

Si potrebbe specificare il DateTimeKind all'interno della query:

from x in ourDataContext.SomeTable 
select DateTime.SpecifyKind(x.DT, DateTimeKind.Utc) 

Se si farà questo, spesso, un metodo di estensione potrebbe contribuire a rendere meno prolissa:

public static class Ext 
{ 
    public static DateTime AsUtc(this DateTime dateTime) 
    { 
     return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc); 
    } 

    public static DateTime? AsUtc(this DateTime? dateTime) 
    { 
     if(dateTime == null) return null; 
     return AsUtc(dateTime.Value); 
    } 
} 

Allora la vostra la domanda diventa:

from x in ourDataContext.SomeTable select x.DT.AsUtc() 
+0

Ciò interrompe l'idea di delegare la funzionalità a Linq2Sql. Se alcuni sviluppatori dimenticano di usare AsUtc, riceveranno dati errati. – Dima

3

Linq2Sql genera classi parziali per tabelle, facilitando così l'estensione. Basta aggiungere SomeTable.cs file alla soluzione (all'interno dello stesso spazio dei nomi come il vostro contesto db auto-generata) e definire una proprietà in più con qualsiasi comportamento è necessario:

public partial class SomeTable { 
    public System.DateTime CustomDT { 
     get { return DT.AddYears(120); } 
    } 
} 

ora è possibile interrogare come al solito:

 var e = ctx.SomeTable.Select(x => new { x.CustomDT }).First(); 
     Console.WriteLine(e.CustomDT); 

Aggiornamento:

sulla base delle osservazioni credo che il problema si sta affrontando è dovuto alla separazione non corretta delle responsabilità. Stai cercando di passare una responsabilità di business logic (trasformazione dei dati) al tuo DAL.Mentre L2S offre una certa flessibilità qui (come mostrato sopra) hai altre opzioni se la soluzione non è soddisfacente:

  1. Livello esplicito sopra L2S DAL. Tipicamente si tratta di un pattern di repository che restituisce DTO molto simili a quelli generati automaticamente da L2S. In questo caso è possibile nascondere la proprietà DT costringendo i consumatori a utilizzare solo CustomDT.
  2. Inserire la logica nel database (viste, colonne calcolate, SP). I non prenderebbe in considerazione questo approccio per un nuovo progetto ma potrebbe essere un'opzione valida per alcune applicazioni legacy.
+0

Questo metodo è descritto nella domanda stessa, ma sto cercando un approccio migliore. – Dima

+0

Non riesco a vedere come la domanda descriva l'utilizzo di una proprietà extra che risolve il problema. Funziona sia in proiezione (come nell'esempio) che in scenari di selezione. – UserControl

+0

Bene, è semplice: dobbiamo introdurre codice personalizzato, che presenta due svantaggi: 1. uno sviluppatore di terze parti non può ancora utilizzare direttamente la proprietà DT (quindi l'intera idea della proprietà DT automatizzata è interrotta) 2. mentre si utilizza CustomDT nelle query, LINQ2SQL ignora l'ottimizzazione: richiede tutti i campi della tabella dal database invece di richiedere solo il campo DT. – Dima

0

Si potrebbe utilizzare linq-to-sql per la porzione di query e utilizzare linq-to-objects per afferrare la proprietà DateTime si vuole (non sono in realtà restituendo un tipo anonimo).

(From x In ourDataContext.SomeTable _ 
Select x).AsEnumerable() _ 
      .Select(Function(x) x.DT) 
0

Puoi provare questo codice? Invece di usare il tipo Anonimo, puoi specificare lo stesso tipo di tabella ma caricare solo un campo. Non so se funzionerà o meno nel tuo caso.

SomeTable.Select(x => new SomeTable { 
    DateField = x.DateField 
}) 

Altrimenti non esiste una soluzione semplice.

Problemi correlati