Как вернуть набор результатов со столбцами с Linq - PullRequest
1 голос
/ 02 апреля 2011

У меня есть функция внутри класса, которая будет запускать запрос Linq to Entities (или любой другой тип запроса Linq), и он будет возвращать 2 столбца в наборе результатов.Я хотел бы вернуть объект тому, кто вызывает мою функцию, что позволит Intellisense узнать, что я возвратил.
Позвольте мне объяснить.Если у меня есть такая функция:

public static IQueryable GetInfo(MyEntityModel oEntityModel)
{
  var query =
    (from t in oEntityModel.Table1
     from u in t.Table2
     where t.Status == true &&
     u.Status == true
     select new
     {
       t.Column1,
       u.Column2
     })
  return query;
}

Что я могу (должен) поместить вместо IQueryable, чтобы тот, кто вызывает мою функцию GetInfo, получал Intellisense из набора результатов и показывал, что она имеет Column1 иСтолбец2?

var linqresult = ClsLinqTeste.GetInfo(oEntityModel);
if (linqresult.Column1 == 1)
{
  foreach (var oItem in linqresult)
  {
    .. do stuff...
  }
}

Ткс

Ответы [ 5 ]

3 голосов
/ 02 апреля 2011

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

См. Этот вопрос , и это сообщение в блоге .

Чтобы вы могли создать простую структуру или класс:

public class MyDataResult
{
    public object Column1 { get; set; }
    public object Column2 { get; set; }
}

Затем измените свой запрос в функции:

public static IQueryable<MyDataResult> GetInfo(MyEntityModel oEntityModel)
{
  var query =
    (from t in oEntityModel.Table1
     from u in t.Table2
     where t.Status == true &&
     u.Status == true
     select new MyDataResult
     {
       Column1 = t.Column1,
       Column2 = u.Column2
     })
  return query;
}

Нечто подобное должно работать.Обратите внимание, что я использовал «объект» для свойств в MyDataResult.Я не знаю типы столбцов, которые вы возвращаете, вы должны использовать фактические типы, чтобы получить полную интеллигенцию.

2 голосов
/ 02 апреля 2011

Вы возвращаете коллекцию анонимных типов, они будут преобразованы в объекты, поэтому, когда вы попытаетесь выполнить итерации по ним, они будут вашими объектами (и они будут содержать ваши свойства) во время компиляции, к которым они будут преобразованы.объекты:

foreach (var x in ClsLinqTeste.GetInfo(oEntityModel))
{
  //x is an Object
}

Подробнее об этом можно прочитать здесь .

Если вы хотите иметь intellisense, я предлагаю вам создать собственный класс, в котором будут храниться ваши свойстваи вернуть не анонимный тип (используя new {}), а объект вашего класса (new MyClass(prop1, prop2)).Вам также необходимо изменить сигнатуру вашего метода, чтобы он возвращал IQueryable<YourClass>, а не просто не-универсальный IQueryable.

1 голос
/ 02 апреля 2011

Как уже говорили другие, создание нового типа для хранения двух столбцов обычно является наилучшим вариантом.

Но если по какой-то причине вы не хотите этого делать и используете .Net4.0, вы можете использовать Tuple:

public static IQueryable<Tuple<Column1Type, Column2Type>>
    GetInfo(MyEntityModel oEntityModel)
{
  return from …
         select Tuple.Create(t.Column1, u.Column2);
}


var linqresult = ClsLinqTeste.GetInfo(oEntityModel);
foreach (var oItem in linqresult)
  Console.WriteLIne(oItem.Item1, oItem.Item2);
0 голосов
/ 02 апреля 2011

Если вы хотите строго типизировать перечисление неуниверсального IEnumerable (IEnumerable.GetEnumerator() вместо IEnumerable<T>.GetEnumerator<T>()), вы можете использовать расширение Cast <> (), например,

 var myquery = GetQueryable();

 for (var item in myquery.Cast<MyDataType>())
 {
       // use item.Column1 directly and strongly typed with intellisense
 }
0 голосов
/ 02 апреля 2011

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

Вот что вы делаете:

var linqresult = ClsLinqTeste.GetInfo(oEntityModel);
if (linqresult.Column1 == 1)
{
  ..do stuff...
}

Вот как вы должны это сделать:

var linqresult = ClsLinqTeste.GetInfo(oEntityModel);

foreach(var item in linqresult)
{
  if (item.Column1 == 1)
  {
    ..do stuff...
  }
}

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

...