不允许在查询中显式构造实体类型'###'。

时间:2009-04-24 19:45:40

标签: linq-to-sql

使用Linq命令和Linq To SQL datacontext,我试图以这种方式从我的datacontext实例化一个名为“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 个答案:

答案 0 :(得分:21)

可以在查询之外创建实体,并使用DataContext将其插入到数据存储中。然后,您可以使用查询检索它们。但是,您无法将实体创建为查询的一部分。

答案 1 :(得分:15)

我发现这个限制非常烦人,并且违背了在查询中不使用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 };

如果属性的名称与数据库列匹配,我们可以在查询中更简单地执行选择

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

可以继续写一个lambda表达式,它可以根据属性名自动复制,而不需要明确指定值。

答案 2 :(得分:12)

我发现如果在尝试构造新对象之前对查询执行.ToList(),则可以使用

答案 3 :(得分:11)

这是另一个解决方法:

  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. 将结果转换回Order,如下所示:

    return query.Cast<Order>().ToList(); // or .FirstOrDefault()
    
  4. (或者使用更合理的东西,比如BLToolkit / LINQ to DB)

  5. 注意:我还没有通过测试来查看跟踪是否有效;它可以检索数据,这就是我需要的。

答案 4 :(得分:9)

我刚遇到同样的问题。

我找到了一个非常简单的解决方案。

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 :(得分:5)

我构造一个匿名类型,使用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 });

答案 6 :(得分:0)

在“使用Microsoft .NET Framework 4进行Web应用程序开发 - 自定进度训练工具包”一书中,第638页有以下示例将结果输出到强类型对象:

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

Mark Pecks的建议似乎与本书相矛盾 - 但是,对我来说这个例子仍然显示上述错误,让我有点困惑。这与版本差异有关吗?欢迎任何建议。

答案 7 :(得分:0)

我找到了另一个问题的解决方法,甚至可以让你将结果保留为IQueryale,因此它实际上不会执行查询,直到你希望它被执行(就像使用ToList()方法)。

所以linq不允许你创建一个实体作为查询的一部分?您可以将该任务转移到数据库本身,并创建一个可以获取所需数据的函数。将函数导入数据上下文后,只需将结果类型设置为所需的结果类型即可。


当我必须编写一段产生IQueryable<T>的代码时,我发现了这一点,其中的项目实际上并不存在于包含T的表中。