选择使用EF代码第一次从数据库中的特定列(Select Specific Columns from

2019-07-30 11:08发布

我们有一个客户非常大的表有超过500列(我知道有人做的!)

许多这些列实际上外键与其他表

我们也有要求, 急于负载一些相关的表格。

有没有办法在LINQ to SQL或动态LINQ到指定要从数据库中检索哪些列? 我在寻找,实际上对生成的SQL语句这种效果LINQ的声明:

SELECT Id, Name FROM Book

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

任何帮助深表感谢!


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

我希望我可以设置到相关实体的唯一负载有限列如Id和名称(其在UI用来查看记录到用户)

我猜的另一种选择是控制什么FK列应该急于加载。 然而,这仍然是问题,为有你可能不希望加载所有的时间二进制或ntext列表。

有没有办法钩多个模型(实体)到同一个表中的Code First? 我们试着这样做我觉得努力遭到惨败。

Answer 1:

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

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到对象的数据。

编辑:

有可能是一些误会EF是如何工作的。 EF适用于实体的顶部 - 实体已映射什么。 如果500列映射到实体,EF只需使用该实体为您定义它。 这意味着查询负载实体和持久保存的实体。

为什么是这样工作的? 实体被认为是原子数据结构和数据可以装载和跟踪只有一次 - 这是正确坚持更改回数据库能力的一个重要特征。 这并不意味着,如果你需要它,但你应该明白,列载子集不定义你的原始实体,你应该不加载列的唯一子集 - 这被认为是对你的实体数据的任意视图。 这种观点不跟踪和不费一番周折(仅仅是因为EF没有持有有关投影原点的任何信息)并不能被持续回数据库。

EF也对映射实体的能力,一些额外的限制

  • 每个表都可以正常映射一次。 为什么? 同样因为映射表多次以不同的实体可以打破正确地坚持这些实体的能力 - 例如,如果任何非键列映射两次,加载映射到同一记录两个实体,你会在使用的映射值的实例保存更改?
  • 有两个例外,允许你映射表中多次
    • 每层次结构的继承表 - 这是表可以包含从在继承层次结构定义的多个实体类型的记录的映射。 在层次结构映射到基础机构列必须由所有实体共享。 每一个派生实体类型都可以有自己的列映射到其特定的性质(其他实体类型具有这些列总是为空)。 这是不可能的多个实体之间的衍生属性共享列。 还必须有一个叫哪个实体类型存储在记录鉴别告诉EF附加列 - 因为它已经映射为型判别该列不能被映射为财产。
    • 表分裂 - 这是对单表映射限制直接的解决方案。 它可以让你的表分割成一些约束多个实体:
      • 必须有实体之间的一个一对一的关系。 你必须用来加载核心数据的一个中央实体和所有其他实体都通过这个实体导航属性访问。 预先加载,延迟加载和明确的负载正常工作。
      • 的关系是真正的1-1这样两个部分或关系必须始终存在。
      • 实体不得共享任何财产,除了关键 - 这个约束将解决最初的问题,因为每个修改的属性映射只有一次
      • 从分解表的每个实体必须有一个映射关键属性
      • 插入需要整个对象图来填充,因为其他实体可以包含映射所需的列

LINQ到SQL还包含标记列延迟加载能力,但该功能目前无法使用在EF -你可以投票给该功能 。

它会导致你的选择进行优化

  • 使用投影来获得只读实体“视图”
    • 你可以这样做,在Linq查询,因为我在这个答案的前一部分显示
    • 您可以创建数据库视图,并将其映射为一个新的“实体”
    • 在EDMX你也可以使用定义查询或查询视图来封装SQL或ESQL投影在你的映射
  • 使用表拆分
    • EDMX允许你拆分表到许多实体没有任何问题
    • 代码首先,您可以拆分表以及但是当你拆表超过两个实体(我认为,这需要每个实体类型有导航属性从分割表中的所有其他实体类型也存在一些问题-这使得它真的很难用)。


Answer 2:

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



文章来源: Select Specific Columns from Database using EF Code First