8

我有一个简单的表:

身份证 | 价值

当我这样做时:

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.contenx 是 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?

编辑 2 使用开箱即用的 linq2Sql 提供程序。我已经围绕它构建了一些通用包装器,但它们不会改变代码中 IQuaryable 或 IEnumerable 函数的方式。

4

4 回答 4

6

下面是什么valuesVault.GetTable()

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

这意味着 that valuesVault.GetTable()is 的 typeIQueryable反过来意味着整个 query 变成了一个expression

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

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

您可以做的是通过调用or方法来强制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()。这就是使语句从IQueryableto 变为IEnumerable的原因,这将改变它的行为。

于 2011-03-10T21:29:58.843 回答
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 };
于 2011-03-10T21:31:51.017 回答
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 }
于 2011-03-10T21:31:53.973 回答
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,然后执行您的选择,您将获得不同的 Guid。

于 2011-03-10T21:31:47.050 回答