Анонимный тип с Linq и Guid - PullRequest
       39

Анонимный тип с Linq и Guid

8 голосов
/ 11 марта 2011

У меня есть простая таблица:

ID | Значение

Когда я делаю это:

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

каждый элемент в проекции имеет значение одной и той же направляющей ... Как мне записать это так, чтобы я получил различное случайное значение направляющей для каждого из моих элементов в проекции?

Редактировать

Для уточнения вопроса. Метод GetTable () просто вызывает это:

        return this.context.GetTable<T>();

где this.contenxt - это DataContext типа T.

Итого сделано как всегда, ничего сложного:

     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 ]

6 голосов
/ 11 марта 2011

Что под valuesVault.GetTable()?

Возможно, у вас есть поставщик Linq, такой как Linq 2 SQL.

Это означает, что valuesVault.GetTable() имеет тип IQueryable, что, в свою очередь, означает, что весь запрос становится выражением .

Выражение - это запрос , который определен, но еще не выполнен.

Когда sequence повторяется, запрос выполняетсяиспользуя поставщика Linq и этого поставщика Linq, и один из шагов, которые он должен выполнить, - выполнить это выражение: Guid.NewGuid().Большинство провайдеров Linq не могут передать это выражение в базовый источник (SQL Server не будет знать, что с ним делать), поэтому оно выполняется один раз, а результат выполнения возвращается с остальным результатом.

ЧтоВы можете сделать так, чтобы выражение valuesVault.GetTable() стало collection , вызвав методы .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, и это изменит его поведение.

4 голосов
/ 11 марта 2011

Я думаю, что это происходит, когда он переводится в 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 голосов
/ 11 марта 2011

Кажется, работает на меня.

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 }
1 голос
/ 11 марта 2011

Я не могу воспроизвести это поведение с помощью простого запроса 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, а затем выполните свой выбор, вы получите разные направляющие.

...