C# LINQ到实体-实体框架
我希望能更好地理解我们应该在什么时候使用C# LINQ到实体-实体框架,c#,linq-to-entities,entity-framework-5,C#,Linq To Entities,Entity Framework 5,我希望能更好地理解我们应该在什么时候使用IEnumerable而不是IQueryable和LINQ to Entities 对于真正基本的数据库调用,IQueryable要快得多,但是什么时候我需要考虑使用一个IEnumerable来代替它呢 其中,IEnumerable是IQueryable的最优值吗?IEnumerable表示一系列元素,您可以逐个枚举这些元素,直到找到所需的答案,例如,如果我想要所有属性大于10的实体,我需要依次检查每一个,只返回匹配的。为了做到这一点,将数据库表的每一行都
IEnumerable
而不是IQueryable
和LINQ to Entities
对于真正基本的数据库调用,IQueryable
要快得多,但是什么时候我需要考虑使用一个IEnumerable
来代替它呢
其中,
IEnumerable
是IQueryable
的最优值吗?IEnumerable
表示一系列元素,您可以逐个枚举这些元素,直到找到所需的答案,例如,如果我想要所有属性大于10的实体,我需要依次检查每一个,只返回匹配的。为了做到这一点,将数据库表的每一行都拉入内存可能不是一个好主意
另一方面,IQueryable
表示一组元素,在这些元素上,过滤之类的操作可以推迟到底层数据源,因此在过滤的情况下,如果我要在自定义数据源上实现IQueryable
(或使用LINQ to Entities!)然后我可以对数据源(例如数据库)进行过滤/分组等艰苦工作
IQueryable
的主要缺点是实现它相当困难-查询被构造为表达式树,作为实现者,您必须解析表达式树才能解析查询。如果你不打算写一个提供者,那么这不会伤害你
IQueryable的另一个值得注意的方面(尽管这实际上只是一个关于将处理传递给另一个系统的一般警告,该系统可能会对世界做出不同的假设)是,您可能会发现字符串比较之类的东西以源系统中支持的方式工作,不是以使用者实现它们的方式,例如,如果源数据库不区分大小写,但.NET中的默认比较区分大小写。
IEnumerable
表示一系列元素,您可以逐个枚举这些元素,直到找到所需的答案,例如,如果我想要所有属性大于10的实体,我需要依次检查每个实体,只返回匹配的实体。为了做到这一点,将数据库表的每一行都拉入内存可能不是一个好主意
另一方面,IQueryable
表示一组元素,在这些元素上,过滤之类的操作可以推迟到底层数据源,因此在过滤的情况下,如果我要在自定义数据源上实现IQueryable
(或使用LINQ to Entities!)然后我可以对数据源(例如数据库)进行过滤/分组等艰苦工作
IQueryable
的主要缺点是实现它相当困难-查询被构造为表达式树,作为实现者,您必须解析表达式树才能解析查询。如果你不打算写一个提供者,那么这不会伤害你
IQueryable的另一个值得注意的方面(尽管这实际上只是一个关于将处理传递给另一个系统的一般警告,该系统可能会对世界做出不同的假设)是,您可能会发现字符串比较之类的东西以源系统中支持的方式工作,不是以使用者实现它们的方式,例如,如果源数据库不区分大小写,但.NET中的默认比较区分大小写。基本上,iQueryTables由查询提供程序(例如数据库)执行,某些操作不能或不应该由数据库执行。例如,如果您想使用从数据库中获得的值调用C#函数(这里是一个示例,请正确大写名称),您可以尝试以下操作:
db.Users.Select(x => Capitalize(x.Name)) // Tries to make the db call Capitalize.
.ToList();
由于Select
是在IQueryable上执行的,并且底层数据库不知道您的Capitalize
函数,因此查询将失败。相反,您可以做的是从数据库中获取正确的数据,并将IQueryable转换为IEnumerable(这基本上只是在内存中迭代集合的一种方式),以便在本地内存中执行其余操作,如中所示
db.Users.Select(x => x.Name) // Gets only the name from the database
.AsEnumerable() // Do the rest of the operations in memory
.Select(x => Capitalize(x)) // Capitalize in memory
.ToList();
从EF的角度来看IQueryable与IEnumerable的性能最重要的一点是,您应该始终尝试使用IQueryable筛选数据,以获得尽可能少的数据来转换为IEnumerable。
AsEnumerable
调用基本上是告诉数据库“按现在筛选的方式将数据提供给我”,如果不进行筛选,则会将所有内容都提取到内存中,甚至是您可能不需要的数据。基本上,iQueryTables由查询提供程序(例如数据库)执行有些操作不能或不应该由数据库完成。例如,如果您想使用从数据库中获得的值调用C#函数(这里是一个示例,请正确大写名称),您可以尝试以下操作:
db.Users.Select(x => Capitalize(x.Name)) // Tries to make the db call Capitalize.
.ToList();
由于Select
是在IQueryable上执行的,并且底层数据库不知道您的Capitalize
函数,因此查询将失败。相反,您可以做的是从数据库中获取正确的数据,并将IQueryable转换为IEnumerable(这基本上只是在内存中迭代集合的一种方式),以便在本地内存中执行其余操作,如中所示
db.Users.Select(x => x.Name) // Gets only the name from the database
.AsEnumerable() // Do the rest of the operations in memory
.Select(x => Capitalize(x)) // Capitalize in memory
.ToList();
从EF的角度来看IQueryable与IEnumerable的性能最重要的一点是,您应该始终尝试使用IQueryable筛选数据,以获得尽可能少的数据来转换为IEnumerable。aseneumerable
调用的基本功能是告诉数据库“按现在筛选的方式将数据提供给我”,如果不进行筛选,则会将所有内容提取到内存中,甚至是不需要的数据