2012-03-01 20 views
5

Sto usando Entity Framework 4.3, POCO, base di dati prima e sto ottenendo il seguente errore:Come aggirare l'errore "Provider di dati .NET Framework interno 1025."?

errore Provider interno di dati .NET Framework 1025.

DOMANDA: Credo che la mia domanda esprime il mio intento, ma mi sembra di colpire questo errore, quindi mi chiedo se qualcuno sa come potrei strutturare la mia query in modo diverso per aggirare questo errore?

Ecco lo scenario ...

Ho un database SQL Server 2008, che ha 2 tavoli - A e B:

Un

  • Aid (int - non null - identità - chiave primaria)
  • AName (nvarchar (10) - non null)

B

  • BID (int - non nullo - identità - chiave primaria)
  • SomeName (nvarchar (10) - non nullo)
  • Aid (int - non nullo - chiave esterna di collegamento per aiutare nella tabella a)

poi definisco contesto in questo modo:

public class DatabaseContext : DbContext 
{ 
    public DatabaseContext(string name) 
     : base(name) 
    { 
     Configuration.AutoDetectChangesEnabled = false; 
     As = Set<A>(); 
     Bs = Set<B>(); 
    } 

    public DbSet<A> As { get; private set; } 
    public DbSet<B> Bs { get; private set; } 
} 

e le classi di entità in questo modo:

public class A 
{ 
    public int AId { get; set; } 
    public string AName { get; set; } 
    public virtual ICollection<B> Bs { get; private set; } 

    public void AddB(B b) 
    { 
     if (b == null) 
     { 
      throw new ArgumentNullException("b"); 
     } 

     if (Bs == null) 
     { 
      Bs = new List<B>(); 
     } 

     if (!Bs.Contains(b)) 
     { 
      Bs.Add(b); 
     } 

     b.A = this; 
    } 
} 

public class B 
{ 
    public int BId { get; set; } 
    public A A { get; set; } 
    public string SomeName { get; set; } 
} 

Ora per la query ...

Quello che voglio è tutto il come, dove ogni "B SomeName" è nella lista dei nomi fornito in modo faccio questo:

var names = new[] {"Name1", "Name2"}; 

var ctx = new DatabaseContext("EFPlayingEntities"); 
var res = ctx.As.Where(a => a.Bs.Select(b => b.SomeName).All(names.Contains)); 

// Here I evaluate the query and I get: 
// Internal .NET Framework Data Provider error 1025. 
Console.WriteLine(res.Count()); 

essere chiari su quello che voglio dire, se i dati della tabella si presenta così:

AId,AName 
1,A1 
2,A2 
3,A3 
4,A4 

BId,SomeName,AId 
1,Name1,1 
2,Name2,1 
3,Name1,2 
4,Name1,3 
5,Name3,3 
6,Name1,4 
7,Name2,4 

Mi aspetterei di tornare A1, A2 e A4 (in modo che la chiamata di conteggio sopra restituisca 3).

+0

Hai guardato in eccezione interna? –

+0

L'eccezione interna è nulla :-( – kmp

+0

names.Contains non è un codice valido, non è sicuro di come compila. Sospetto che tu voglia utilizzare Intersect() invece di All(). –

risposta

8

Il motivo per cui questo accade è sottile.

Queryable.All deve essere chiamato con un Expression. Passando solo il metodo 'reference' crea un delegato, e successivamente, Enumerable.All diventa il candidato invece del previsto Queryable.All.

Ecco perché la soluzione che hai inviato come risposta funziona correttamente.

EDIT

quindi se si scrive l'istruzione come questo, funzionerà senza eccezione:

var res = ctx.As.Where(
    a => a.Bs.Select(b => b.SomeName).All(b => names.Contains(b))); 
+0

Woah! Quindi, anche se. All (b => names.Contains (b)) è funzionalmente (intendo in termini di ciò che fa, non come lo fa) equivalente a. All (names.Contains) quello che stai dicendo è il sottostante il meccanismo è diverso e ho trovato un bug nell'EF quando sta valutando l'albero delle espressioni? Ho appena provato e questo "ctx.As.Where (a => a.Bs.Select (b => b.SomeName) .All (b => names.Contains (b)))" esegue infatti senza errori ! Grazie! – kmp

+0

Spero non ti dispiaccia, ho aggiunto un po 'alla tua risposta in modo che se qualcun altro si imbatte in questo vedrà subito il cambiamento che hai suggerito. – kmp

+0

@ user1039947: Nessun problema :) Questo non è un bug EF, ma piuttosto una funzionalità mancante con il compilatore di espressioni di C#. – leppie

2

Ho trovato una soluzione a questo, nel caso qualcuno fosse interessato. Facendo seguito è equivalente e non comporta l'eccezione nella domanda:

var res = ctx 
    .Bs 
    .GroupBy(b => b.A) 
    .Where(g => g.All(b => names.Contains(b.SomeName))) 
    .Select(g => g.Key); 

Non so se questo è il modo migliore se !?

1

La semantica della tua query mi sembra buona; chiaramente, ottenere un errore interno del provider non è il comportamento previsto! Mi sarei aspettato un messaggio più esplicito su EF non essere in grado di tradurre la tua query in un'operazione di negozio, se è in realtà qual è il problema.

Un altro modo per fare quello che vuoi sarebbe:

var names = new[] {"Name1", "Name2"}; 
var nameCount = names.Length; 

var ctx = new DatabaseContext("EFPlayingEntities"); 
var result = ctx.As 
    .Where(a => a.Bs 
       .Select(b => b.SomeName) 
       .Intersect(names) 
       .Count() == a.Bs.Count()); 

(ottenere ogni A tale che intersecano i nomi dei suoi B s'con l'elenco fisso dà tutto il B s)

anche se io porto 'provato questo per vedere se EF può tradurre con successo questo.

Un altro modo:

var names = new[] {"Name1", "Name2"}; 

var ctx = new DatabaseContext("EFPlayingEntities"); 
var result = ctx.As 
    .Where(a => !a.Bs.Select(b => b.SomeName).Except(names).Any()); 

(ottenere ogni A in modo tale che l'elenco dei nomi dei suoi B s'è ridotta a nulla, prendendo l'elenco fisso)

anche intentato.

+0

Grazie per la risposta ed entrambi eseguono bene senza eccezioni! Tuttavia, nessuna delle tue soluzioni corrisponde alla funzionalità di cui ho bisogno per restituire anche A che ha una raccolta di Bs con un sottoinsieme della raccolta di nomi che ho inserito. Nei miei dati di esempio mi aspetto che venga restituito anche A2 poiché contiene "Nome1" al suo interno – kmp

+0

@user oops, ha avuto il sottotitolo nel verso sbagliato; aggiornato la mia risposta. Penso che il modo "Eccetto" sia decisamente il migliore dei due ora. E sì, tutto: il tuo originale, la tua risposta, i miei due modi, tutti hanno la stessa semantica - che scegliere è puramente una questione di gusti e, naturalmente, se EF può tradurre con successo ... – AakashM

Problemi correlati