Linq和Guid的匿名类型

时间:2011-03-10 21:24:05

标签: c# linq guid enumerable

我有一张简单的表:

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。

itteration完成,因为它总是完成,没有什么花哨的:

     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?

编辑2 使用linq2Sql提供程序框。我在它周围构建了一些泛型包装器,但它们并没有改变代码中IQuaryable或IEnumerable函数的方式。

4 个答案:

答案 0 :(得分:6)

valuesVault.GetTable()下面是什么?

您可能拥有Linq提供程序,例如Linq 2 SQL。

这意味着valuesVault.GetTable()属于IQueryable类型,这反过来意味着整个查询变为expression

表达式是已定义但尚未执行的 查询

当迭代sequence时,使用Linq提供程序执行查询,Linq提供程序和它必须执行的步骤之一是执行此表达式:Guid.NewGuid()。大多数Linq提供程序无法将该表达式传递给基础源(SQL Server不知道如何处理它),因此它会执行一次,执行结果将返回结果的其余部分。

您可以通过调用valuesVault.GetTable().ToList()方法强制.ToArray()表达式成为 集合 。这将执行表达式并返回表示内存中集合的IEnumerable

IEnumerable执行查询时,执行不会传递给Linq提供程序,而是由.NET运行时执行。

在您的情况下,这意味着可以正确执行表达式Guid.NewGuid()

试试这个:

var sequence = from c in valuesVault.GetTable().ToArray()
               select new {RandomIDX = Guid.NewGuid(), c.ID, c.Value};

注意那里的 .ToArray()。这将使声明从IQueryable转到IEnumerable,这将改变其行为。

答案 1 :(得分:4)

我认为当它被翻译成SQL时会发生这种情况(即:它是数据库所做的)。由于您的示例中没有WHERE子句,您可以这样做:

var sequence = from c in valuesVault.GetTable().ToList()
               select new { RandomID = Guid.NewGuid(), c.ID, c.Value };

强制Guid.NewGuid()在客户端执行。但是,如果你的表增长并且你开始添加过滤子句,那就太难看了。您可以使用第二个LINQ查询来解决它,该查询使用新GUID投影第二个结果集:

var sequence = from c in valuesVault.GetTable()
               where c.Value > 10
               select new { c.ID, c.Value };

var finalSequence = from s in sequence.ToList()
                    select new { RandomID = Guid.NewGuid(), s.ID, s.Value };

答案 2 :(得分:2)

似乎适合我。

List<int> a = new List<int> {10, 11, 12, 13};

            var v = a.Select(i => new {ID = Guid.NewGuid(), I = i});
            foreach (var item in v)
            {
                Console.WriteLine(item);
            }

输出

{ ID = b760f0c8-8dcc-458e-a924-4401ce02e04c, I = 10 }
{ ID = 2d4a0b17-54d3-4d69-8a5c-d2387e50f054, I = 11 }
{ ID = 906e1dc7-6de4-4f8d-b1cd-c129142a277a, I = 12 }
{ ID = 6a67ef6b-a7fe-4650-a8d7-4d2d3b77e761, I = 13 }

答案 3 :(得分:1)

我无法使用简单的LINQ查询重现此行为。样品:

List<int> y = new List<int> { 0, 1, 2, 3, 4, 5 };

var result = y.Select(x => new { Guid = Guid.NewGuid(), Id = x }).ToList();

我想象的是,如果你试图将你的Table值转换为Linq中的List,然后执行你的选择,你会得到不同的Guids。