我编写了LINQ to Entities,它正在使用以下OrderBy:
.OrderBy(i => Guid.NewGuid())
上面随机化了数据集的顺序,因此每次运行此代码时都会产生不同的顺序。
但是,如果我执行以下任何操作,则数据集不是随机的,并且是所有3个OrderBy的完全相同,见下文:
.OrderBy(i => new Guid("5fd3e5e7-b172-42f5-a4dd-da4212201a31"))
.OrderBy(i => new Guid("beb7345c-1421-48e0-b177-51b2bb065214"))
Guid g = Guid.NewGuid();
.OrderBy(i => g)
你可以看到上面的3个OrderBy正在使用不同的Guid,那么他们为什么要生成相同的订单呢?为什么每次运行这段代码时Guid.NewGuid()都会将列表随机化,但是其他3个OrderBy语句每次产生相同的结果?
我的问题是,我需要将一个值传入一个函数,该函数在LINQ to Entities数据集中用于根据值随机化结果,但是我还需要能够传递相同的值并检索相同的随机顺序。
感谢。
答案 0 :(得分:8)
当您拥有Guid.NewGuid()时,这种行为是在Entity Framework中设计的,它模仿SQL的ORDER BY NEWID(),以允许随机排序。当你指定一个常量Guid时,它只是按这个常量值排序。
答案 1 :(得分:5)
为什么他们生产相同的订单?
因为它们为每一行返回相同的值。传递给private void method1(){
int var = 500;
Field.value(var); }
的表达式将针对每一行执行,以产生表示该行的顺序的值。实际上,using Guid.NewGuid()
as expression for OrderBy()
can cause different problems,因为它不稳定(在连续调用同一行时返回不同的值)。另一方面,Guid.NewGuid()
should be translated to NEWID()
,否定了这个问题。
因此,固定的GUID将为每一行返回相同的值。
我需要将一个值传递给一个函数,该函数在LINQ to Entities数据集中用于根据值随机化结果
然后重新设计该功能。
答案 2 :(得分:2)
代码.OrderBy(i => Guid.NewGuid())
传递一个表达式,该表达式针对每一行进行求值,以找到要按其排序的内容。写得像这样,对于每个值,它将再次调用Guid.NewGuid()
,返回不同的 GUID,并为每一行提供随机(ish)值以进行排序。< / p>
这与调用Guid.NewGuid()
并将结果传递给.OrderBy(i => g)
不同,因为这会一遍又一遍地返回相同的 GUID,这意味着GUID没有对排序有影响,并且收集按照默认的方式排序 - 可能只是按照它们之前的顺序保留它们。
答案 3 :(得分:-1)
更新:我的原始答案对于LINQ和lambdas来说是正确的,但不适用于LINQ to Entities(我希望他们称之为LINQ for Entity Framework ...)。我只是错过了那部分问题,感谢@Servy指出了这一点。我添加了一个LINQ to Entities段落。
对于 LINQ to Objects (其中源数据由.NET对象集合组成,例如List&lt; T &gt;,数组等),这是会发生什么:
.Where(x => IsAllowed(x))
或.OrderBy(x => SomeValue())
等子句中的 lambda语句对于每个处理的项目执行一次。您编写的代码不是立即执行,而是成为LINQ方法的参数,如果&amp;和LINQ执行它。什么时候需要它。
这意味着,在您的情况下,每个项目都会执行i => Guid.NewGuid()
,每次都会创建一个新值。
这不仅仅是LINQ的一个特殊功能,它可以应用于任何地方,但LINQ肯定会使用它。
如果您使用自己的方法,例如.OrderBy(i => MyMethod())
然后在MyMethod
内放置一个断点,然后您将看到它被调用0,1或多次,具体取决于正在处理的项目。然后,从Debug Call Stack中,您可以看到您在LINQ执行路径中。
对于 LINQ to Entities ,事情甚至有点复杂。它仍然将您编写的代码作为参数,但这次它只接受可以直接转换为底层数据库的SQL语句的代码。
As we can see,具有Guid.NewGuid()
正文的lambda被LINQ to EF识别,并在生成的SQL语句中变为NEWID()。所以虽然最终的结果和行为非常相似,但这次它是数据库所在的随机的&#39;生成guid,每行一次。
因为所有内容都必须与SQL兼容/可翻译,所以很多代码现在都是非法的。使用MyMethod
(因此您自己的代码)的上述示例现在不起作用,因为只有非常特定的.NET Framework调用才能转换为SQL。