Можно ли вернуть IEnumerable анонимных объектов из DataContext.ExecuteQuery? - PullRequest
4 голосов
/ 14 мая 2009

Я разрабатываю механизм отчетности, в котором отчеты основаны на шаблонах. Каждый шаблон имеет строку с запросом SQL, а каждый отчет имеет определенные значения для параметров запроса SQL. Чтобы создать отчет, я устанавливаю параметры и вызываю метод DataContext.ExecuteQuery , чтобы получить список записей. Но чтобы перехватить возвращаемые столбцы, я должен знать их имена и иметь класс с соответствующими свойствами.

Можно ли как-то вернуть IEnumerable анонимных объектов из DataContext.ExecuteQuery, а затем определить их свойства с помощью Reflection?

Мне нужен эквивалент LINQ для SqlDataReader.GetValues ​​.

Спасибо!

Ответы [ 3 ]

4 голосов
/ 15 мая 2009

Пока у нас нет C # 4.0 с ключевым словом dynamiciс , мы можем использовать это решение (слегка измененный код из статьи Выполнение произвольных запросов в LINQ to SQL от Октавио Эрнандеса Лила):

public static class DataContextExtension
{
    public static IEnumerable<Dictionary<string, object>> ExecuteQuery(this DataContext dataContext, string query)
    {
        using (DbCommand command = dataContext.Connection.CreateCommand())
        {
            command.CommandText = query;
            dataContext.Connection.Open();

            using (DbDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection))
            {
                while (reader.Read())
                {
                    Dictionary<string, object> dictionary = new Dictionary<string, object>();

                    for (int i = 0; i < reader.FieldCount; i++)
                        dictionary.Add(reader.GetName(i), reader.GetValue(i));

                    yield return dictionary;
                }
            }
        }
    }
}

Этот метод расширения возвращает IEnumerable объектов Dictionary <>, где ключами являются имена столбцов запроса.

0 голосов
/ 14 мая 2009
  • Компилятор не может открыть ваш sql и определить свойства, которые должны существовать.
  • Поскольку вы хотите, чтобы компилятор делал это, я должен заключить, что вы не совсем понимаете анонимную типизацию.

Не используйте LinqToSql для этого. Просто используйте ваш метод чтения данных.

0 голосов
/ 14 мая 2009

Да, вы можете сделать это. Пожалуйста, посмотрите на этот фрагмент.

class Program {
        static void Main(string[] args) {
            var persons = new Person[]{
                new Person{Age=22,Name="John Doe",Id=1},
                new Person{Age=23,Name="Jack Smith", Id=2},
                new Person{Age=34,Name="Sara Parker", Id=3}
            };
            var anonData = GetAnonTypes(persons);
            foreach (var item in anonData as IEnumerable) {
                //use reflection to access propties 
            }
        }
        static object GetAnonTypes(IEnumerable<Person> persons) {
            var query=from p in persons  select new{
                Id=p.Id,
                Name=p.Name
            };
            return query;        
        }
    }

    public class Person {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
...