Domanda

Sto usando LINQ to SQL per MySQL (utilizzando DbLinq) in un sito web ASP.NET MVC. Ho un problema di caching strano. Prendere in considerazione i seguenti metodi della mia classe repository:

public IEnumerable<Message> GetInbox(int userId)
{
  using(MyDataContext repo = new MyDataContext(new MySqlConnection("[Connectionstring]")))
  {
    return repo.Messages.Where(m => m.MessageTo == userId);
  }
}

public IEnumerable<Message> GetOutbox(int userId)
{
  using (MyDataContext repo = new MyDataContext(new MySqlConnection("[Connectionstring]")))
  {
    return repo.Messages.Where(m => m.MessageFrom == userId);
  }
}

'MyDataContext' è il sottoprodotto DbLinq mappatura generata al mio database, che eredita da DataContext. Non sto riutilizzare il DataContext qui (il codice di cui sopra sembra un po 'stupido, ma ho voluto essere assolutamente sicuri che non fosse qualche DataContext / MySqlConnection problema riutilizzo).

Quello che succede è, a seconda di quale dei due metodi che io chiamo, con tutto ciò che userId, i risultati rimangono gli stessi. Periodo. Anche se mi rendo conto che repo.Messages ha più di 10 risultati, con diversi valori MessageFrom e MessageTo, ho solo i primi da query risultati indietro. Quindi se chiamo GetInbox(4374) mi dà un messaggio A e B. messaggio GetInbox(526) Calling poi ancora mi dà un messaggio A e B, anche se c'è sono Messaggi di C e D che non hanno un userId di 526. devo riavviare l'applicazione per visualizzare le modifiche.

Che cosa sta succedendo qui? Sono sicuro che sto facendo qualcosa di così stupido che ho intenzione di vergognarmi quando qualcuno lo fa notare a me. Se io non sto facendo qualcosa di molto stupido, quindi ho trovato questo problema molto strano. Ho letto di non riutilizzare DataContext, ma io non sono. Perché questo problema di cache? Qui di seguito è il mio codice del controller, ma dubito è importante:

[Authorize]
public ActionResult Inbox(int userId)
{
  Mailbox inbox = new Mailbox(userId, this.messageRepository.GetInbox(userId));
  return PartialView("Inbox", inbox);
}

Anche se ci sono domande simili su così, non ho trovato una risposta a questa domanda esatta. Molte grazie!

Aggiorna : modificando il codice a: return repo.Messages.ToList().Where(m => m.MessageFrom == userId); la fissa, funziona benissimo allora. Sembra che qualche problema di cache. Tuttavia, io ovviamente non voglio risolvere il problema in questo modo. Modifica del codice in modo che il DataContext non è disposto dopo che la query non risolvere il problema.

È stato utile?

Soluzione 4

Bene, sembrava che si trattava di un problema con DbLinq. Ho usato il codice sorgente da 3 settimane e c'era un bug apparente in QueryCache (anche se ha sempre stato lì). C'è un filo completo che copre questo qui .

Ho aggiornato la fonte dblinq. Querycache è ora disattivato (implica un calo di prestazioni) e ben almeno ora funziona. Dovrò vedere se le prestazioni sono accettabili. Confesso che sono un po 'perplesso anche se, come quello che sto cercando di fare è un modello comune linq2sql. Grazie a tutti.

Altri suggerimenti

Ho scritto un codice abbastanza simile che sembra funzionare bene. L'unica differenza è che, come suggerisce Marc, sto passando nella stringa di connessione e chiamando ToList sul metodo dove. Il mio database non viene generato automaticamente, ma deriva da DataContext. Il codice è al di sotto.

class Program
{
    static void Main(string[] args)
    {
        List<Item> first = GetItems("F891778E-9C87-4620-8AC6-737F6482CECB").ToList();
        List<Item> second = GetItems("7CA18DD1-E23B-41AA-871B-8DEF6228F96C").ToList();
        Console.WriteLine(first.Count);
        Console.WriteLine(second.Count);
        Console.Read();
    }

    static IEnumerable<Item> GetItems(string vendorId)
    {
        using (Database repo = new Database(@"connection_string_here"))
        {
            return repo.GetTable<Item>().Where(i => i.VendorId.ToString() == vendorId).ToList(); ;
        }
    }
}

Inizio scrivendo un test. Questo vi dirà montone castrato Linq2Sql si sta comportando in modo corretto. Qualcosa di simile:

var inboxMessages = this.messageRepository.GetInbox(userId1);
Assert.That(inboxMessages.All(m => m.MessageTo == userId1);

inboxMessages = this.messageRepository.GetInbox(userid2);
Assert.That(inboxMessages.All(m => m.MessageTo = userid2);

Se questo riesce, si dovrebbe davvero controllare montone castrato è l'esecuzione differita che sta causando problemi. Si dovrebbe enumerare inboxMessages subito.

Un'altra cosa che potrebbe essere la causa problemi, è il fatto che si avvia l'enumerazione quando il DataContext è già smaltito. L'unico modo per risolvere questo problema, non è quello di disporre affatto (e si basano sul GC pulirlo quando va fuori portata), o venire con un oggetto IDisposable personalizzato, in modo da poter mettere un utilizzo intorno ad esso. Qualcosa di simile:

using(var inboxMessages = this.messageRepository.GetInbox(userId1))
{
    Assert.That(inboxMessages.All(m => m.MessageTo == userId1);
}

La memorizzazione nella cache in LINQ to SQL è associato con il DataContext, ed è prevalentemente limitato all'identità caching - nella maggioranza dei casi si ri-eseguire una query anche se non hai fatto prima. Ci sono alcuni esempi, come .Single(x=>x.Id == id) (che ha un trattamento speciale).

Dato che si sta chiaramente diventando un nuovo data-contesto ogni volta, non credo che sia il colpevole. Tuttavia, sono anche un po 'sorpreso che il codice funziona ... sei sicuro che è rappresentativo?

metodo Where di LINQ è differito - che significa che non viene eseguito fino a quando si scorrere i dati (ad esempio con foreach). Ma da quel momento non si è conservato il contesto dati! Avete snipped qualcosa dall'esempio?

Inoltre - dandogli un SqlConnection (che non si allora Dispose()), si può essere impattare la pulizia -. Può essere preferibile basta dargli (il dato contesto) la stringa di connessione

Eviterei usando DBLinq per codice di produzione ... molti di LINQ to SQL funzioni di non sono implementati, e camminare attraverso il codice sorgente mostra un basso livello di maturità ... molti dei metodi non sono implementati o contrassegnati come "terminato".

... siete stati avvertiti!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top