【问题标题】:LINQ left-join Entity Frame work - Unable to create a constant value of typeLINQ 左连接实体框架 - 无法创建类型的常量值
【发布时间】:2012-01-23 18:13:14
【问题描述】:

有些类似问题的答案在我的情况下不起作用。

我来了

无法创建“.Model.featureoptions”类型的常量值。此上下文仅支持原始类型(“例如 Int32、String 和 Guid”)。

使用实体优先,EntityFramework 4.1,MVC3,C# 4。

vehicles 是车辆详细信息表,owners 是车主表。 vehiclesowners 是内部连接的,并且有效。

features 表是可选功能的列表,例如天窗、油漆等。featureOptions 是一个功能可用选项的列表。例如油漆可以是“珠光”、“matalic”,天窗可以是“玻璃弹出”、“标题+幻灯片”。

vehicleFeatures 是为车辆选择的选项列表,对于特定功能,车辆可以有零个或一个记录。

在此查询中,feature1 应为 null 或功能的选定值(即所选天窗选项),feature2 应为 null 或不同功能的所选值(即所选油漆选项)

var query = (from v in _entities.vehicles

                 join o
                    in _entities.owners
                    on v.OwnerID equals o.OwnerID

                 // Some more inner joins

                 select new
                 {
                     // <code snipped >
                     // o. fields and v. fields
                     // </ code snipped>

                     feature1 = (from feature1
                                     in _entities.vehiclefeatures
                                     .Where ( f_1 => f_1.VehicleID == v.VehicleID)
                                 join feature1_fo
                                     in _entities.featureoptions
                                 on feature1.FeatureOptionID equals feature1_fo.FeatureOptionID
                                 join feature1_f
                                     in _entities.features
                                     .Where (bt_f => bt_f.CodeEnum==1)
                                 on feature1_fo.FeatureID equals feature1_f.FeatureID
                                 select new featureoptionsDTO () { Option = feature1_fo.Option }
                               ),
                      feature2 = (from feature2
                                         in _entities.vehiclefeatures
                                         .Where(f_2 => f_2.VehicleID == v.VehicleID)
                                      join feature2_fo
                                         in _entities.featureoptions
                                      on feature2.FeatureOptionID equals feature2_fo.FeatureOptionID
                                      join feature2_f
                                          in _entities.features
                                         .Where(feature2_f => feature2_f.CodeEnum == 2)
                                      on feature2_fo.FeatureID equals feature2_f.FeatureID
                                      select new featureoptionsDTO() { Option = feature2_fo.Option }
                                 )
                 }
);

foreach (var vehicle in query)  // Exception here
{
}

feature1 = (from ..

feature2 = (from .. 

导致

无法创建“.Model.featureoptions”类型的常量值。此上下文仅支持原始类型(“例如 Int32、String 和 Guid”)。

我知道 LINQ 正在尝试创建一个实体,我怎样才能让它创建一个匿名(或自己的类)呢?

【问题讨论】:

  • 这个项目还处于早期阶段。考虑更改为 LinqToSql,但数据库是 MySQL,所以需要像 LightSpeed link 这样的东西。
  • 您的模型中没有导航属性吗?或者你为什么要写这么多显式连接?

标签: c# linq entity-framework left-join


【解决方案1】:

不幸的是,Entity Framework 无法处理在 LINQ to Entities 查询中构造任意类型的 select 子句。我自己也被这个绊倒了几次,这很烦人。然而,这是非常必要的,因为 LINQ to Entities 查询被转换为 SQL 以在数据库上运行,而数据库无法处理 .NET 对象的构造。能够在查询结束时执行此操作可能会很好,但肯定不能在中间进行。

我倾向于编写一个查询,该查询准确地生成所有 LINQ to Entities 中的构造函数所需的输入,以便它在数据库上运行。然后在您从中获得的 IQueryable 上调用 ToEnumerable(),这会将其转换为 IEnumerable,然后您将进入 LINQ to Objects,以便您可以在 Select() 中做任何您喜欢的事情。

【讨论】:

  • 啊,有道理。但不确定如何实施您的建议,是否在第二次点击中使用左连接进行两个查询?
  • 如果您不打算以任何其他方式使用该列表,最好不要调用 queryable.ToList().Select(...)。您可以使用大致相同的含义调用 queryable.AsEnumerable().Select(...) ,但无需创建您永远不会使用的 List 对象,也无需直接执行查询。如果您确实需要或想要立即执行查询,请在最后一步调用 ToList():queryable.AsEnumerable().Select(...).ToList()。
  • 或者更确切地说,是不是用第二个查询替换了左连接的两个查询。
  • @hvd 你说得对,我已经编辑了答案以考虑到这一点。 ToEnumerable() 更合适,除非你需要这个列表来做其他事情。
【解决方案2】:

我通过使用数据库中的视图进行外部连接来解决这个问题,然后 linq 查询与视图关联的实体。

通过在数据库中进行左外连接意味着外连接更早完成,可能会使其更快一些。 linq 更整洁,只需要做它需要做的事情,在这种情况下就是过滤。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多