min*_*ods 10 linq-to-entities group-by entity-framework-4
是否可以通过对象执行组?
from item in context.Items
group item by item.MyObject
select ...
Run Code Online (Sandbox Code Playgroud)
其中Item.MyObject是一个简单的对象,例如:
public class MyObject {
public int SomeValue { get; set; }
public string SomeName { get; set; }
public string SomeOtherProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
显然我可以做到以下几点:
from item in context.Items
group item by new { item.SomeValue, item.SomeName, item.SomeOtherProperty }
select ...
Run Code Online (Sandbox Code Playgroud)
但是,当按具有大量属性的对象进行分组时,这种方法很繁琐且容易出错.
上面的代码导致NotSupportedException,并带有以下消息:"对'GroupBy'方法的调用的密钥选择器类型在底层存储提供程序中不具有可比性".覆盖Equals和GetHashcode没有任何影响.我猜真正的问题是实体框架不知道如何表达SQL ......?
可怜,不,你不能这样做.ComplexType看起来很有前景,似乎是一个很好的"列组" - 但EF团队只是将其设计为完全其他用途,并且大量缺少与使用它作为"列组"相关的功能.
据我所知,"显然我可以做到以下几点:"是唯一可行的方法.您只需要在每个子列的基础上定义分组,或者通过投影到某种类型,数据库将知道如何比较.
核心问题是EF团队认为ComplexType 不是一组允许您用多个字段整理实体的列,但是,对于它们来说,它是另一种类型的实体,即一种瞬态实体.ComplexType用于表示从存储过程(或表返回函数)返回的对象,这些对象返回无法映射到任何正常现有表/类的5列结果集.例如,假设您有一个包含50个列/字段的表/类Customer,其中大多数不是null并且表示一些敏感数据.您创建一个存储过程,该过程获取客户的ID并返回其{名称,地址,联系电话,鞋号}.显然,如果设置了这样的修剪结果,则无法将其解码/映射到具有大量不能为空的字段的Customer类.那么你如何在EF中表示结果集?
第一个选项,相当蹩脚的一个,就是简单地忽略EF并直接与数据库通信,并手动读取/翻译/解包行/列.好吧,我们知道SqlClient,我们可以做到.
第二个选项,丑陋的选择,是在EF中定义一个存根表/视图,例如CustomerView,它只包含{name,address,contact phone,shoe size}列,并将存储过程结果集映射到它.它可以很好地工作,但如果您偶然'生成数据库'形成EF模型,您将获得额外的未使用的表也..
救援的第三个选择是ComplexType.您只需告诉EF"有一些额外的数据类型",它永远不会映射到它自己的表,而且永远不会定义一个PrimaryKey,而EF将为您提供,而不是尝试制作一个影子表或视图.便利性将其映射到类,就像任何其他数据对象一样.现在,有这样的类型,你可以从程序返回它并将其作为一个很好的类型对象检索,你可以将它作为过程的参数传递等等.但是:你不能自己坚持它.它没有自己的表映射,也没有自己的主键.它没有身份.
这很好,但是,为什么你想要从程序返回这样的数据类型?可能是,该过程处理或生成了一些数据,并且您希望将它们存储在某个表中.您尚未定义整个普通实体,因此该事物只是一个"数据包",因此您可能会将该结果值与其他数据一起写入该表.这就是为什么EF允许你将ComplexType映射到表的某些列:如果你从一个过程获得了那个临时结果对象,现在你想在某个地方写它,你不必逐列手动完成它,您只需将其映射到客户的"姓名,地址,联系电话,鞋号"栏目.
最重要的一点是,数据库服务器永远不会知道存在这样的ComplexType.正如我所说,它没有身份.当您尝试执行LINQ查询时
aset.Where(item => item.complexProperty == complexValue)
Run Code Online (Sandbox Code Playgroud)
那么,complexValue是一个没有映射到任何表的CLR对象,没有NO,因此没有PK,因此EF完全没有IDEA如何检查"左手对象"是否与"右手对象"相同.如果对象定义了一些标识,它可以检查服务器端的PK,或者在客户端进行对象引用比较,但是在这里 - 它只是失败了.
我完全同意这是EF中另一个该死的有用功能.我相信EF团队很容易在逐列的基础上比较ComplexTypes,但他们没有.他们根本不认为ComplexTypes可以用于整理表格.它们意味着它是一个瞬态数据包,可以传递到存储过程和函数.Pity.