Явная конструкция типа сущности '###' в запросе не допускается. - PullRequest
37 голосов
/ 24 апреля 2009

Используя команды Linq и текстовый текст Linq To SQL, я пытаюсь создать экземпляр объекта «Produccion» из моего текстового текста следующим образом:

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();

При выполнении вышеприведенного кода я получаю следующую ошибку, включающую трассировку стека:

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: 

Это теперь разрешено в LINQ2SQL?

Ответы [ 8 ]

21 голосов
/ 24 апреля 2009

Объекты могут быть созданы вне запросов и вставлены в хранилище данных с использованием DataContext. Затем вы можете получить их с помощью запросов. Однако вы не можете создавать объекты как часть запроса.

15 голосов
/ 09 августа 2012

Я считаю, что это ограничение очень раздражает и противоречит общей тенденции не использовать SELECT * в запросах.

Тем не менее, для анонимных типов в c # есть обходной путь, выбирая объекты в анонимный тип, а затем копируя его в правильный тип.

Например:

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 
   }));

А в случае, когда мы имеем дело с одним значением (как в ситуации, описанной в вопросе), это еще проще, и нам просто нужно напрямую скопировать значения:

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 };

Если имена свойств совпадают со столбцами базы данных, мы можем сделать это еще проще в запросе, выполнив select

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

Можно написать лямбда-выражение, которое можно автоматически копировать на основе имени свойства, без необходимости явно указывать значения.

12 голосов
/ 11 января 2013

Я обнаружил, что если вы делаете .ToList () в запросе, прежде чем пытаться создать новые объекты, это работает

11 голосов
/ 19 декабря 2013

Вот еще один обходной путь:

  1. Создайте класс, производный от вашего класса LINQ to SQL. Я предполагаю, что класс L2S, который вы хотите вернуть, это Order:

    internal class OrderView : Order { }
    
  2. Теперь напишите запрос следующим образом:

    var query = from o in db.Order
                select new OrderView // instead of Order
                {
                   OrderID = o.OrderID,
                   OrderDate = o.OrderDate,
                   // etc.
                };
    
  3. Приведите результат обратно в порядок, как это:

    return query.Cast<Order>().ToList(); // or .FirstOrDefault()
    
  4. (или используйте что-нибудь более разумное, например BLToolkit / LINQ to DB)

Примечание. Я не проверял, работает ли отслеживание; он работает для извлечения данных, а это то, что мне нужно.

9 голосов
/ 30 апреля 2009

Я только что столкнулся с той же проблемой.

Я нашел очень простое решение.

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;
5 голосов
/ 30 января 2014

Я создаю анонимный тип, использую IEnumerable (который сохраняет отложенное выполнение), а затем заново создаю объект datacontext. И Employee, и Manager являются объектами 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 });
0 голосов
/ 21 марта 2014

Я нашел другой обходной путь для проблемы, который даже позволяет вам сохранить ваш результат как IQueryale, поэтому он фактически не выполняет запрос, пока вы не захотите его выполнить (как это было бы с методом ToList ()).

То есть linq не позволяет вам создавать сущность как часть запроса? Вы можете перенести эту задачу в саму базу данных и создать функцию, которая будет получать нужные вам данные. После того, как вы импортируете функцию в контекст данных, вам просто нужно установить тип результата, который вы хотите.


Я узнал об этом, когда мне пришлось написать кусок кода, который бы вывел IQueryable<T>, в котором элементы фактически не существуют в таблице, содержащей T.

0 голосов
/ 25 июня 2012

В книге "70-515 Разработка веб-приложений с помощью Microsoft .NET Framework 4 - Самообучающийся учебный комплект" на стр. 638 приведен следующий пример вывода результатов в строго типизированный объект:

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

Совет Марка Пека, кажется, противоречит этой книге - однако, для меня этот пример все еще показывает вышеупомянутую ошибку, оставляя меня несколько смущенным. Это связано с различиями версий? Любые предложения приветствуются.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...