Не удается получить тот же результат из DataContext.Translate - PullRequest
0 голосов
/ 24 июня 2011

Этот вопрос является продолжением этого вопроса: Как создать список из двух значений

Рассмотрим этот код:

class MainClass() 
{
   string MainKey {get;set;}
   string MainName {get;set;}
   IEnumerable<SmallObject> MainList {get;set} 
}

class SmallObject() 
{
   string SmallKey {get;set} 
} 

и:

var mainQuery = (from v from DataContext.myTable
                 select v);

var myQuery = (from v in mainQuery
               select new MainClass()
               {
                  MainKey = v.Field1,
                  MainName = v.Field2,
                  MainList = new []
                  {
                     new SmallObject { SmallKey = v.Field3 },
                     new SmallObject { SmallKey = v.Field4 },
                  }
                });


var result1 = myQuery.ToList();

//Changing datatypes for optimization reasons in SQLServer2000
var cmd = DataContext.GetCommand(myQuery);
foreach (System.Data.Common.DbParameter param in cmd.Parameters)
{
  // nvarchar -> varchar
  // decimal -> numeric
}
var result2 = DataContext.Translate<MainClass>(cmd.ExecuteReader()).ToList();

result1.MainList в порядке

result2.MainList равен null

Исходный запрос был очень медленным при работе с SQLServer2000, и я получил его при изменении типов данных (Linq используетnvarchar и decimal, поскольку в моей базе данных используются varchar и numeric)

Поэтому я хочу, чтобы result2 был таким же, как result1, но этого не происходит при выполнении DataContext.Translate следующим образом.

Есть мысли о том, чтобы получить такой же результат?

Я также пробовал анонимные типы, например:

IEnumerable<object> MainList {get;set;}
...
MainList = new []
{
   new { SmallKey = v.Field3},
   new { SmallKey = v.Field4},
}

, но результат тот же:

Ответы [ 2 ]

1 голос
/ 24 июня 2011

Я думаю, что вы слишком много просите от Translate.

Если я вас правильно понял, это первый запрос (mainQuery), который слишком медленный, поэтому я хотел бы заменить его.

Я бы создал более простой временный класс, такой как

 public class TmpClass
 {
    public string Field1 {get;set;}
    public string Field2 {get;set;}
    public string Field3 {get;set;}
    public string Field4 {get;set;}
 } 

Как только список будет в этом формате, вы можете использовать второй запрос, чтобы изменить его на список MainClass.

Просто вопрос, в чем разница между sql, выводимым Linq, и вашей настроенной версией?Если он не выполняет кастинг, я бы не ожидал, что этот тип запросов нуждается в оптимизации.

0 голосов
/ 24 июня 2011

Я бы использовал метод расширения AsEnumerable , который в основном преобразует IQueryable в IEnumerable, который заставляет перечислитель обрабатываться.Вы можете добиться того же, позвонив по номеру ToArray() или ToList(), но AsEnumerable() волшебным образом вернет его обратно к IQueryable, позвонив по номеру AsQueryable()

Так что, вероятно, выполнение следующего будет работать для вас:

var result1 = DataContext.myTable.AsEnumerable()
  .Select(v=> new MainClass {
                  MainKey = v.Field1,
                  MainName = v.Field2,
                  MainList = new []
                  {
                     new SmallObject { SmallKey = v.Field3 },
                     new SmallObject { SmallKey = v.Field4 },
                  }
         });
...