Domanda La costruzione esplicita del tipo di entità "###" nella query non è consentita.


Utilizzando i comandi Linq e il datacontext Linq To SQL, sto provando ad istanziare un'entità chiamata "Produccion" dal mio datacontext in questo modo:

Demo.View.Data.PRODUCCION pocoProduccion = 
(
    from m in db.MEDICOXPROMOTORs
    join a in db.ATENCIONs on m.cmp equals a.cmp
    join e in db.EXAMENXATENCIONs on a.numeroatencion equals e.numeroatencion
    join c in db.CITAs on e.numerocita equals c.numerocita
    where e.codigo == codigoExamenxAtencion
    select new Demo.View.Data.PRODUCCION
    {
         cmp = a.cmp,
         bonificacion = comi,
         valorventa = precioEstudio,
         codigoestudio = lblCodigoEstudio.Content.ToString(),
         codigopaciente = Convert.ToInt32(lblCodigoPaciente.Content.ToString()),
         codigoproduccion = Convert.ToInt32(lblNroInforme.Content.ToString()),
         codigopromotor = m.codigopromotor,
         fecha = Convert.ToDateTime(DateTime.Today.ToShortDateString()),
         numeroinforme = Convert.ToInt32(lblNroInforme.Content.ToString()),
         revisado = false,
         codigozona = (c.codigozona.Value == null ? Convert.ToInt32(c.codigozona) : 0),
         codigoclinica = Convert.ToInt32(c.codigoclinica),
         codigoclase = e.codigoclase,
    }
).FirstOrDefault();

Durante l'esecuzione del codice precedente, ricevo il seguente errore che include la traccia dello stack:

System.NotSupportedException was caught
  Message="The explicit construction of the entity type 'Demo.View.Data.PRODUCCION' in a query is not allowed."
  Source="System.Data.Linq"
  StackTrace:
       en System.Data.Linq.SqlClient.QueryConverter.VisitMemberInit(MemberInitExpression init)
       en System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
       en System.Data.Linq.SqlClient.QueryConverter.Visit(Expression node)
       en System.Data.Linq.SqlClient.QueryConverter.VisitSelect(Expression sequence, LambdaExpression selector)
       en System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc)
       en System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression mc)
       en System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
       en System.Data.Linq.SqlClient.QueryConverter.Visit(Expression node)
       en System.Data.Linq.SqlClient.QueryConverter.VisitFirst(Expression sequence, LambdaExpression lambda, Boolean isFirst)
       en System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc)
       en System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression mc)
       en System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
       en System.Data.Linq.SqlClient.QueryConverter.ConvertOuter(Expression node)
       en System.Data.Linq.SqlClient.SqlProvider.BuildQuery(Expression query, SqlNodeAnnotations annotations)
       en System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
       en System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Expression expression)
       en System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
       en Demo.View.InformeMedico.realizarProduccionInforme(Int32 codigoExamenxAtencion, Double precioEstudio, Int32 comi) en D:\cs_InformeMedico\app\InformeMedico.xaml.cs:línea 602
       en Demo.View.InformeMedico.UpdateEstadoEstudio(Int32 codigo, Char state) en D:\cs_InformeMedico\app\InformeMedico.xaml.cs:línea 591
       en Demo.View.InformeMedico.btnGuardar_Click(Object sender, RoutedEventArgs e) en D:\cs_InformeMedico\app\InformeMedico.xaml.cs:línea 683
  InnerException: 

È ora consentito in LINQ2SQL?


35
2018-04-24 19:45


origine


risposte:


Le entità possono essere create al di fuori delle query e inserite nell'archivio dati utilizzando un DataContext. È quindi possibile recuperarli utilizzando le query. Tuttavia, non è possibile creare entità come parte di una query.


21
2018-04-24 19:52



Sto trovando questa limitazione di essere molto fastidioso, e andando contro la tendenza comune di non usare SELECT * nelle query.

Ancora con i tipi anonimi c # c'è una soluzione alternativa, recuperando gli oggetti in un tipo anonimo e quindi copiandolo nel tipo corretto.

Per esempio:

var q = from emp in employees where emp.ID !=0
select new {Name = emp.First + " " + emp.Last, EmployeeId = emp.ID }
var r = q.ToList();
List<User> users = new List<User>(r.Select(new User
   {
        Name = r.Name,
        EmployeeId = r.EmployeeId 
   }));

E nel caso in cui trattiamo un singolo valore (come nella situazione descritta nella domanda) è ancora più semplice, e abbiamo solo bisogno di copiare direttamente i valori:

var q = from emp in employees where emp.ID !=0 
select new { Name = emp.First + " " + emp.Last, EmployeeId = emp.ID }
var r = q.FirstOrDefault();
User user = new User { Name = r.Name, EmployeeId = r.ID };

Se il nome delle proprietà corrisponde alle colonne del database, possiamo farlo anche più facilmente nella query, facendo select

var q = from emp in employees where emp.ID !=0 
select new { emp.First, emp.Last, emp.ID }

Si potrebbe andare avanti e scrivere un'espressione lambda che può essere copiata automaticamente in base al nome della proprietà, senza la necessità di specificare esplicitamente i valori.


14
2017-08-08 21:33



Ho appena incontrato lo stesso problema.

Ho trovato una soluzione molto semplice.

var a = att as Attachment;

Func<Culture, AttachmentCulture> make = 
    c => new AttachmentCulture { Culture = c };

var culs = from c in dc.Cultures
           let ac = c.AttachmentCultures.SingleOrDefault( 
                                           x => x.Attachment == a)
           select ac == null ? make(c) : ac;

return culs;

9
2018-04-30 07:23



Ho scoperto che se fai una .ToList () sulla query prima di provare a contrare nuovi oggetti funziona


9
2018-01-11 09:42



Ecco un'altra soluzione:

  1. Crea una classe che deriva dal tuo LINQ alla classe SQL. Suppongo che la classe L2S che si desidera restituire sia Order:

    internal class OrderView : Order { }
    
  2. Ora scrivi la query in questo modo:

    var query = from o in db.Order
                select new OrderView // instead of Order
                {
                   OrderID = o.OrderID,
                   OrderDate = o.OrderDate,
                   // etc.
                };
    
  3. Rimetti il ​​risultato in Ordine, in questo modo:

    return query.Cast<Order>().ToList(); // or .FirstOrDefault()
    
  4. (o usare qualcosa di più sensato, come BLToolkit / LINQ to DB)

Nota: non ho testato per vedere se il tracciamento funziona o meno; funziona per recuperare i dati, che è quello che mi serviva.


7
2017-12-19 01:42



Costruisco un tipo anonimo, utilizzo IEnumerable (che conserva l'esecuzione differita) e quindi ri-consruct l'oggetto datacontext. Sia Dipendente che Manager sono oggetti datacontext:

    var q = dc.Employees.Where(p => p.IsManager == 1)
            .Select(p => new { Id = p.Id, Name = p.Name })
            .AsEnumerable()    
            .Select(item => new Manager() { Id = item.Id, Name = item.Name });

5
2018-01-30 18:47



All'interno del libro "70-515 Sviluppo di applicazioni Web con Microsoft .NET Framework 4 - Kit di formazione autonomo", pagina 638 ha il seguente esempio per produrre risultati in un oggetto fortemente tipizzato:

    IEnumerable<User> users = from emp in employees where emp.ID !=0
    select new User
    {
    Name = emp.First + " " + emp.Last,
    EmployeeId = emp.ID
    }

Il consiglio di Mark Peck sembra contraddire questo libro - tuttavia, per me questo esempio mostra ancora l'errore di cui sopra, lasciandomi un po 'confuso. Questo è legato alle differenze di versione? Qualsiasi suggerimento benvenuto.


0
2018-06-25 09:33



Ho trovato un altro modo per risolvere il problema che consente anche di mantenere i risultati come IQueryale, quindi in realtà non esegue la query finché non si desidera che venga eseguita (come con il metodo ToList ()).

Quindi linq non ti permette di creare un'entità come parte della query? È possibile spostare tale attività nel database stesso e creare una funzione che catturerà i dati desiderati. Dopo aver importato la funzione nel contesto dei dati, è sufficiente impostare il tipo di risultato su quello desiderato.


Ho scoperto questo quando ho dovuto scrivere un pezzo di codice che avrebbe prodotto un IQueryable<T> in cui gli oggetti non esistono realmente nella tabella contenente T.


0
2018-03-21 16:00