2012-07-17 114 views
11

我们有一个客户非常大的表超过列(我知道有人做的!)使用EF代码第一次

许多列实际上外键与其他表数据库选择特定的列

我们也有要求急切加载一些相关的表格。

Linq to SQL或Dynamic Linq有什么方法可以指定从数据库中检索哪些列? 我找的,实际上,在生成SQL语句这种影响一个LINQ声明:

SELECT Id, Name FROM Book 

当我们运行由EF生成的络查询,SQL Server将引发一个错误,你已经达到的最大列数可以在查询中选择!

任何帮助非常感谢!


恰好是这种情况,表中有500列,是自参考我们的工具会自动加载心切的第一级关系,这击中上可以查询的列数的SQL限制。

我希望我可以设置到相关的实体,例如Id和名称(其在UI用来查看记录到用户)

我想另一种选择是仅负载有限列控制什么FK列应该急切加载。但是,对于具有二进制或ntext列的表而言,这仍然存在问题,您可能不希望一直加载该列。

有没有办法将多个模型(实体)绑定到Code First中的同一个表上?我们试图这样做,我认为这一努力失败了。

回答

18

是的,你可以通过使用投影返回列的唯一子集:

var result = from x in context.LargeTable 
      select new { x.Id, x.Name }; 

问题:投影和预先加载不一起工作。一旦你开始使用投影或自定义连接,你正在改变查询的形状,并且你不能使用Include(EF会忽略它)。在这种情况下,唯一的办法就是手动包括在投影结果集的关系:

var result = from x in context.LargeTable 
      select new { 
       Id = x.Id, 
       Name = x.Name, 
       // You can filter or project relations as well 
       RelatedEnitites = x.SomeRelation.Where(...) 
      }; 

您也可以投射到具体的类型,但是特定类型不能映射(所以你不能例如项目LargeTable实体从我的样品)。对映射实体的投影只能在Linq-to-objects中的物化数据上完成。

编辑:

EF可能存在一些误解。 EF在实体之上工作 - 实体就是你所映射的。如果您将500列映射到实体,则EF只需按照您定义的那样使用该实体。这意味着查询加载实体并坚持保存实体。

为什么它以这种方式工作?实体被认为是原子数据结构,其数据只能被加载和跟踪一次 - 这是能够将更改正确保存到数据库的关键功能。这并不意味着如果你需要的话,你不应该只加载列的子集,但你应该明白加载列的子集并没有定义你的原始实体 - 它被认为是你实体中数据的任意视图。这个视图不会被追踪,并且无需额外的努力就不会被保存回数据库(因为EF没有关于投影的起源的任何信息)。

EF也放在一些能力的附加约束映射中的每个表都可以正常映射仅一旦实体

  • 。为什么?同样,因为多次将映射表映射到不同实体可能会破坏正确保存这些实体的能力 - 例如,如果任何非键列被映射两次,并且您加载映射到相同记录的两个实体的实例,您将在哪些映射值期间使用保存更改?
  • 有两个例外,允许你映射表中多次
    • 表每一个分层的继承 - 这是表可以包含在继承层次结构中定义多个实体类型记录的映射。映射到层次结构中的基础实体的列必须由所有实体共享。每个派生实体类型都可以将其自己的列映射到其特定属性(其他实体类型都将这些列始终为空)。无法在多个实体之间共享派生属性的列。还必须有一个名为discriminator的额外列,告诉EF哪些实体类型存储在记录中 - 此列不能映射为属性,因为它已经映射为类型鉴别器。
    • 表分割 - 这是单表映射限制的直接解决方案。它允许您将表格拆分为多个实体,并具有一些限制条件:
      • 实体之间必须存在一对一的关系。您有一个用于加载核心数据的中央实体,所有其他实体都可以通过此实体的导航属性进行访问。正常加载,延迟加载和显式加载正常工作。
      • 该关系是真实的1-1所以两个部分或关系必须始终存在。
      • 实体不得共享任何财产键除外 - 这种约束将解决最初的问题,因为每个修改的属性是从分解表映射只有一次
      • 每个实体必须有一个映射关键属性
      • 插入需要整个对象要填充图表因为其他实体可以包含映射所需的列

LINQ到-SQL还包含标记的列作为能力延迟装入但THI s功能目前无法在EF中使用 - 您可以使用vote for that feature

它会导致你的选择优化

  • 用突起获得只读实体
    • “视图”你可以做,在Linq查询,因为我在这之前的部分显示回答
    • 您可以创建数据库视图,并将其映射为一个新的“实体”
    • 在EDMX你也可以使用定义查询或查询视图来封装SQL或ESQL投影在你的映射
  • 使用表拆分
    • EDMX允许您拆分表格许多实体没有任何问题
    • Code first allows you splitting table很好,但也存在一些问题,当你分解表超过两个实体(我认为,这需要每个实体类型具有导航属性到分割表中的所有其他实体类型 - 这使得它很难使用)。
+0

我希望有更可靠的方式来指定列。在许多情况下,我们的MVC应用程序为多个模型共享,我们使用动态LINQ来为不同的表执行相同的查询。 – sam360 2012-07-17 19:54:46

+0

动态linq也应该能够指定投影。 EF是用于处理实体的工具 - 实体就是您已经映射的实体=如果您已将500列映射到实体,则您的查询无投影将始终返回500列+所有已加载关系的列。 – 2012-07-17 20:23:55

+0

是的,情况就是这样,表格有500列,并且自动引用我们的工具,自动加载第一级关系,这对于可以查询的列数有SQL限制。 我希望我可以设置为只加载相关实体的有限列,如Id和Name(用于在UI中查看记录给用户) 我想另一个选项是控制哪些列应该急于加载。然而,对于具有二进制或ntext列的表,您可能不希望加载所有联系,这仍然存在问题。 – sam360 2012-07-17 20:59:06

0

创建查询所需的列数的存储过程,然后从代码中调用存储的特效。