Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 4 实体框架GroupBy对象或ComplexType_Entity Framework 4_Linq To Entities_Group By - Fatal编程技术网

Entity framework 4 实体框架GroupBy对象或ComplexType

Entity framework 4 实体框架GroupBy对象或ComplexType,entity-framework-4,linq-to-entities,group-by,Entity Framework 4,Linq To Entities,Group By,是否可以对对象执行分组方式 from item in context.Items group item by item.MyObject select ... 其中Item.MyObject是一个简单对象,例如: public class MyObject { public int SomeValue { get; set; } public string SomeName { get; set; } public string SomeOtherProperty {

是否可以对对象执行分组方式

from item in context.Items
group item by item.MyObject
select ... 
其中Item.MyObject是一个简单对象,例如:

public class MyObject {
    public int SomeValue { get; set; }
    public string SomeName { get; set; }
    public string SomeOtherProperty { get; set; }
}
显然,我可以做到以下几点:

from item in context.Items
group item by new { item.SomeValue, item.SomeName, item.SomeOtherProperty }
select ... 
但是,当按具有大量属性的对象进行分组时,这种方法既繁琐又容易出错


上述代码导致NotSupportedException,并显示以下消息:“在基础存储提供程序中,调用'GroupBy'方法的键选择器类型不可比较”。重写Equals和GetHashcode没有任何效果。我猜真正的问题是实体框架不知道如何表达SQL…?

遗憾的是,不,你不能这么做。ComplexType看起来很有希望,看起来是一个很好的“列组”——但EF团队只是将其设计为完全其他用途,而与将其用作“列组”相关的大量功能完全缺失

就我所知,“显然我可以做到以下几点:”是唯一可能的方法。您只需根据每个子列定义分组,或者通过对数据库将知道如何比较的某种类型的投影来定义分组

核心问题是,EF团队认为ComplexType不是一组列,允许您用许多字段整理实体,但对他们来说,是另一种实体,一种暂时的实体。ComplexType表示从存储过程(或表返回函数)返回的对象,该存储过程返回的结果集为5列,无法映射到任何正常的现有表/类。例如,假设您有一个表/类客户,其中包含50个列/字段,其中大多数不为null,并表示一些敏感数据。您创建了一个存储过程,该过程接受客户ID并返回其{姓名、地址、联系电话、鞋号}。显然,有了这样的修剪结果集,您无法将其解码/映射到包含大量不能为null的字段的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)
然后,complexValue是一个CLR对象,它没有映射到任何表,没有标识,因此没有PK,因此EF完全不知道如何检查“左手对象”是否与“右手对象”相同。如果定义了对象的一些标识,它可以在服务器端检查PK,或者在客户端进行对象引用比较,但是在这里,它只是失败了


我完全同意这是EF中另一个缺失的非常有用的功能。我相信EF团队比较每一列的复杂类型是非常容易的,但是他们没有。他们根本没有想到ComplexTypes可以用来整理表格。它们意味着它是一个临时数据包,可以从存储过程和函数传递到存储过程和函数。。可惜。

我的对象是EF模型的一部分吗?我可以对
MyObject
上的导航属性执行类似的操作(其中MyObject:Item是n:1)。生成的SQL很糟糕,但至少可以工作。它实际上是一个ComplexType。简言之,是的,EF知道对象类型。因为所有属性实际上都存在于同一个表中,所以我希望得到的SQL比使用导航属性时要干净得多(当然,如果我能让它工作的话!)附带说明:我说的是比较,因为我最近在尝试对复杂类型进行筛选/where时偶然发现了这一点。分组是相似的,这一切归结为一个“不知道如何比较”的问题。如果有人知道任何变通方法或EF扩展,我也非常乐意知道。到目前为止,我只发现一些文章说“对不起,这还没有提供,也许在EF5中”谢谢你的深入回答-这是另一个在未来版本中看到的功能。