什么是Guid.NewGuid()在LINQ to Entities中做什么?

时间:2017-01-05 14:36:10

标签: c# entity-framework linq

我编写了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数据集中用于根据值随机化结果,但是我还需要能够传递相同的值并检索相同的随机顺序。

感谢。

4 个答案:

答案 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段落。

  1. 对于 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执行路径中。

  2. 对于 LINQ to Entities ,事情甚至有点复杂。它仍然将您编写的代码作为参数,但这次它只接受可以直接转换为底层数据库的SQL语句的代码。

    As we can see,具有Guid.NewGuid()正文的lambda被LINQ to EF识别,并在生成的SQL语句中变为NEWID()。所以虽然最终的结果和行为非常相似,但这次它是数据库所在的随机的&#39;生成guid,每行一次。

    因为所有内容都必须与SQL兼容/可翻译,所以很多代码现在都是非法的。使用MyMethod(因此您自己的代码)的上述示例现在不起作用,因为只有非常特定的.NET Framework调用才能转换为SQL。