2015-09-25 4 views
5

Nel database dell'applicazione Web ASP.NET MVC 4/EF 5 ho una tabella con una colonna Commenti su cui concatenare nuovi commenti. Nel tradizionale T-SQL, mi piacerebbe scrivere: Come causare a EF la creazione dell'aggiornamento SQL con stringa concat?

UPDATE MyTable SET Comments = 'Hi' + CHAR(13)+CHAR(10) + Comments WHERE ID = 2 

trovo con metodo LINQ per EF (UOW + Pattern Repository - che mi dispiace), devo interrogare prima il valore corrente di Commenti e anteporre i miei nuovi commenti ad esso:

StringBuilder displayComment = new StringBuilder(); 
var item = uow.MyRepos.Where(i => i.ID == 2); 
item.Comments = displayComment.Append("Hi") 
           .Append(Environment.NewLine) 
           .Append(item.Comments) 
           .ToString(); 
uow.Save(); 

C'è un modo per scrivere questo aggiornamento senza la necessità di interrogare il DB? Mi piacerebbe in qualche modo ottenere EF per generare il t-sql sopra. I commenti possono essere lunghi e non mi interessa cosa contenga. Le prestazioni sono una preoccupazione.

Grazie in anticipo.

+1

aggiungo questo qui come un commento, perché non è una risposta: hai ragione su quello che EF può fare, e come fallo. Tuttavia, se hai bisogno di fare qualcosa che EF non supporta, non hai bisogno di spendere energie per cercare di farlo. Puoi semplicemente eseguire una query personalizzata o una stored procedure per risolvere il tuo problema. Può sembrare meno intelligente, ma non penso che lo sia. Ci sono molte cose che EF non può fare, ma * ti è permesso * di fare le cose in altro modo, invece di provare a implementare soluzioni magiche o hacky per il tuo problema. Lo stesso problema si presenta con aggiornamenti di massa o eliminazioni. La soluzione è semplice – JotaBe

+0

Grazie per aver detto questo @JotaBe - Stavo cercando di rimanere all'interno delle linee, ma a volte non è la soluzione migliore. – LoJo

+0

@LoJo hai detto *** Mi piacerebbe in qualche modo ottenere EF per generare il t-sql sopra *** - ecco perché la tua domanda è stata upvoted a *** 5 *** (al momento in cui scrissi questo). Altrimenti è solo un requisito normale, niente di speciale e nemmeno una risposta deve essere aggiunta. Dovresti averlo capito con qualche commento e hai cancellato subito la domanda. – Hopeless

risposta

0

L'aggiornamento standard imposta il campo e presumo che sarà necessario mantenere tale funzionalità, altrimenti non sarà possibile modificare i commenti precedenti. Questo significa che hai un caso di aggiornamento speciale. Vorrei aggiungere un metodo nel repository per MyTable che gestisce l'SQL che si desidera:

public int PrependComment(int id, String comment) 
{ 
    String sql = "UPDATE MyTable SET Comments = {0} + 
     CHAR(13)+CHAR(10) + Comments WHERE ID = {1}"; 
    return dbContext.Database.ExecuteSqlCommand(sql, comment, id); 
} 
+0

Grazie per questo.Ho perso la vista di fare le cose in modo diretto. – LoJo

0

Penso che l'unica cosa con cui puoi giocare sia usare uno DbCommandInterceptor. È possibile intercettare ogni comando non eseguito da query (aggiornare, eliminare, inserire) e modificare il testo del comando prima che venga effettivamente eseguito. Il codice qui è solo per capire come potrebbe essere fatto. È possibile refactoring per un utilizzo più comodo:

public class PrependTextInterceptor : DbCommandInterceptor 
{   
    const string table = "MyTable"; 
    const string column = "Comments"; 
    public override void NonQueryExecuting(DbCommand command, System.Data.Entity.Infrastructure.Interception.DbCommandInterceptionContext<int> interceptionContext) 
    { 
     command.CommandText = Regex.Replace(command.CommandText, 
           string.Format(@"(?i:(?<=^UPDATE \[.+\]\.\[{0}\]\r\nSET .* \[{1}\] =).+?(?=(,|\r\n)))", table, column), "$& + " + column);    
     base.NonQueryExecuting(command, interceptionContext);    
    } 
} 

//Usage 
DbInterception.Add(new PrependTextInterceptor()); 
//after this every time you set the Comments property 
//it will be understood as prepending  
item.Comments = displayComment.Append("Hi") 
           .Append(Environment.NewLine).ToString(); 

Solo un'altra nota, se si carica il vostro item normalmente, la sua proprietà Comments dovrebbe anche essere caricato. Quindi si perde il vantaggio di non caricarlo prima di prepending. Penso che è necessario utilizzare Attach in cui hai solo bisogno di conoscere il ID per essere in grado di aggiornarlo senza caricarla (come come tramite una query context.Set<MyTable>().Single(e => e.ID == 2), Comments quindi dovrebbe essere sicuramente caricato).

+0

Grazie per aver postato questo. Ho deciso di andare con una combinazione di @JotaBe e la raccomandazione di Colin, ma penso che altri potrebbero trovare molto utile. – LoJo

Problemi correlati