使用 Linq 和 Guid 的匿名类型

发布于 2024-10-21 22:17:42 字数 1034 浏览 3 评论 0原文

我有一个简单的表:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

舂唻埖巳落 2024-10-28 22:17:42

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() 可以正确执行。

试试这个:

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

注意那里的 .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 type IQueryable 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 an IEnumerable 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:

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

Notice the .ToArray() there. That is what will make the statement go from IQueryable to IEnumerable and that will change its behaviour.

固执像三岁 2024-10-28 22:17:42

我认为当它被翻译成 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 };

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:

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

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:

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 };
柠檬色的秋千 2024-10-28 22:17:42

似乎对我有用。

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 }

Seems to work for me.

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);
            }

output

{ 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 }
只为一人 2024-10-28 22:17:42

我无法使用简单的 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();

我想象如果您尝试将表值转换为 Linq 中的列表,然后执行选择,您将获得不同的 Guid。

I'm not able to reproduce this behavior with a simple LINQ query. Sample:

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文