实体框架 – 使用EF代码首先从数据库中选择特定列

我们有一个客户非常大的桌子,超过500列(我知道有人这样做!)

其中许多列实际上是其他表的外键.

我们也有要求加载一些相关的表.

Linq到SQL或Dynamic Linq有什么办法可以指定从数据库中检索哪些列?
我正在寻找一个实际上对生成的SQL语句产生这种影响的linq语句:

SELECT Id, Name FROM Book

当我们运行由EF生成的reguar查询时,SQL Server将抛出一个错误,您已达到可在查询中选择的最大列数!

任何帮助深表感谢!

是的,这是这种情况,表有500列,并且自引用我们的工具自动加载第一级关系,并且这可以查询可以查询的列数的SQL限制.

我希望我可以设置只加载相关实体的有限列,如Id和Name(用于UI中的用户查看记录)

我猜另一个选择是控制什么FK列应该加载.但是,对于具有二进制或ntext列的表仍然存在问题,您可能不希望加载所有时间.

有没有办法将多个模型(实体)挂钩到Code First中的同一个表中?我们尝试这样做,我觉得努力失败了.

最佳答案
是的,您可以通过使用投影只返回列的子集:

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

问题:投影和急切加载不能一起工作.一旦您开始使用投影或自定义连接,您正在更改查询的形状,并且您不能使用包含(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-to-Sql还包含将列标记为延迟加载的功能,但此功能目前在EF中不可用 – 您可以使用vote for that feature.

它导致您的优化选择

>使用投影来获取实体的只读“视图”

>你可以在Linq查询中做到这一点,就像我在上面回答的部分所示
>您可以创建数据库视图并将其映射为新的“实体”
>在EDMX中,您还可以使用定义查询或查询视图在映射中封装SQL或ESQL投影

>使用表拆分

> EDMX允许您将表拆分为多个实体,没有任何问题
> Code first allows you splitting table,但是当您将表拆分为两个以上实体时,我们有一些问题(我认为每个实体类型都需要将导航属性与拆分表中的所有其他实体类型相关联 – 这使得它真的很难使用).

转载注明原文:实体框架 – 使用EF代码首先从数据库中选择特定列 - 代码日志