使用 Linq 和 Guid 的匿名类型
我有一个简单的表:
ID |值
当我这样做时:
var sequence = from c in valuesVault.GetTable()
select new {RandomIDX = Guid.NewGuid(), c.ID, c.Value};
投影中的每个元素都具有相同 guid 的值...我该如何编写,以便为投影中的每个元素获得不同的随机 guid 值?
编辑
澄清问题。 GetTable() 方法简单地调用此:
return this.context.GetTable<T>();
其中 this.contenxt 是类型 T 的 DataContext
。迭代按往常方式完成,没有什么花哨的:
foreach (var c in seq)
{
Trace.WriteLine(c.RandomIDX + " " + c.Value);
}
输出:
bf59c94e-119c-4eaf-a0d5-3bb91699b04d What is/was your mother's maiden name?
bf59c94e-119c-4eaf-a0d5-3bb91699b04d What was the last name of one of your high school English teachers?
bf59c94e-119c-4eaf-a0d5-3bb91699b04d In elementary school, what was your best friend's first and last name?
Edit 2 使用开箱即用的 linq2Sql Provider。我围绕它构建了一些通用包装器,但它们不会改变代码中 IQuaryable 或 IEnumerable 函数的方式。
I have a simple table:
ID | Value
When I do this:
var sequence = from c in valuesVault.GetTable()
select new {RandomIDX = Guid.NewGuid(), c.ID, c.Value};
each element in the projection has the value of the same guid... How do I write this so that I get a different random guid value for each of my element in the projection?
Edit
To clarify on the issue. The GetTable() method simply calls this:
return this.context.GetTable<T>();
where the this.contenxt is the DataContext of type T.
The itteration is done as it's always done, nothing fancy:
foreach (var c in seq)
{
Trace.WriteLine(c.RandomIDX + " " + c.Value);
}
Output:
bf59c94e-119c-4eaf-a0d5-3bb91699b04d What is/was your mother's maiden name?
bf59c94e-119c-4eaf-a0d5-3bb91699b04d What was the last name of one of your high school English teachers?
bf59c94e-119c-4eaf-a0d5-3bb91699b04d In elementary school, what was your best friend's first and last name?
Edit 2
Using out the box linq2Sql Provider. I had built some generic wrappers around it but they do not alter the way IQuaryable or IEnumerable function in the code.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
valuesVault.GetTable()
下面是什么?您可能有一个 Linq 提供程序,例如 Linq 2 SQL。
这意味着
valuesVault.GetTable()
的类型为IQueryable
,这又意味着整个查询变成 表达式。表达式是已定义但尚未执行的查询。
迭代
sequence
时,将使用 Linq 提供程序和该 Linq 提供程序执行查询,并且它必须执行的步骤之一是执行以下表达式:Guid.NewGuid()< /代码>。大多数 Linq 提供程序无法将该表达式传递给底层源(SQL Server 不知道如何处理它),因此它只执行一次,然后将执行结果与其余结果一起返回。
您可以做的是通过调用
.ToList()< 来强制
valuesVault.GetTable()
表达式成为集合 /code> 或.ToArray()
方法。这将执行表达式并返回一个表示内存中集合的IEnumerable
。对
IEnumerable
执行查询时,执行不会传递给 Linq 提供程序,而是由 .NET 运行时执行。在您的情况下,这意味着表达式
Guid.NewGuid()
可以正确执行。试试这个:
注意那里的 .ToArray() 。这将使语句从
IQueryable
变为IEnumerable
并改变其行为。What is underneath
valuesVault.GetTable()
?You probably have a Linq provider such as Linq 2 SQL.
That means that
valuesVault.GetTable()
is of typeIQueryable
which in turn means that the entire query becomes an expression.An expression is a query that is defined but not yet executed.
When
sequence
is being iterated over, the query is executed using the Linq provider and that Linq provider and one of the steps it has to perform is to execute this expression:Guid.NewGuid()
. Most Linq providers cannot pass that expression to the underlying source (SQL Server wouldn't know what to do with it) so it gets executed once and the result of the execution returned with the rest of the result.What you could do is to force the
valuesVault.GetTable()
expression to become a collection by calling the.ToList()
or.ToArray()
methods. This executes the expression and returns anIEnumerable
which represents an in-memory collection.When performing queries against an
IEnumerable
, the execution is not passed to the Linq provider but executed by the .NET runtime.In your case this means that the expression
Guid.NewGuid()
can be executed correctly.Try this:
Notice the .ToArray() there. That is what will make the statement go from
IQueryable
toIEnumerable
and that will change its behaviour.我认为当它被翻译成 SQL 时就会发生这种情况(即:是数据库在做这件事)。由于您的示例中没有 WHERE 子句,因此您可以这样做:
这会强制在客户端中执行 Guid.NewGuid() 。但是,如果您的表增长并且您开始添加过滤子句,那就很难看了。您可以通过使用第二个 LINQ 查询来解决这个问题,该查询使用新的 GUID 投影第二个结果集:
I think it's happening when it gets translated into SQL (ie: it's the database doing it). Since you have no WHERE clauses in your example, you could just do:
Which forces Guid.NewGuid() to be executed in the client. However, it's ugly if your table grows and you start adding filtering clauses. You could solve it by using a second LINQ query that projects a second result set with your new GUIDs:
似乎对我有用。
输出
Seems to work for me.
output
我无法使用简单的 LINQ 查询重现此行为。示例:
我想象如果您尝试将表值转换为 Linq 中的列表,然后执行选择,您将获得不同的 Guid。
I'm not able to reproduce this behavior with a simple LINQ query. Sample:
I'm imagining if you try to convert your Table value to a List in Linq, then perform your select, you'll get different Guids.