Используйте метод Subsonic.Select () ExecuteTypedList со строкой - PullRequest
2 голосов
/ 19 мая 2009

Это больше вопрос относительно дженериков, чем дозвуковых:

Представьте, если у вас есть следующий код:

    List<int> result = 
      DB.Select(Product.Columns.Id)
        .From<Product>()
        .ExecuteTypedList<int>();

Это прекрасно работает и возвращает общий список с идентификаторами из моей таблицы Product.

Но если я хочу получить список ProductName:

    List<String> result = 
      DB.Select(Product.Columns.ProductName)
        .From<Product>()
        .ExecuteTypedList<String>();

выдает сообщение компилятора (перевод с немецкого):

«строка» должна быть неабстрактного типа с публичным конструктором без параметр, чтобы использоваться в качестве универсальный тип или в универсальном методе "SubSonic.SqlQuery.ExecuteTypedList ()" в качестве параметра "Т".

причина: в строке нет пустого конструктора:

int i = new int;       // works
String s = new String; // compiler error: "string" does not contain a constructor that takes '0' argument

Если я использую List<Object>, вместо этого он работает , но есть ли более элегантный способ, где я могу использовать List<String>?

Обновление: List<Object> не работает. Я действительно получаю список объектов, но это «пустой» объект, который не содержит мои ProductNames (object.ToString () возвращает {Object})

Ответы [ 4 ]

6 голосов
/ 19 мая 2009

Немного магии дотнетов возможно без исправления дозвукового кода.

  1. Создайте новый класс SubsonicSqlQueryExtensionMethods и удалите этот код:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using SubSonic;
    
    namespace MyUtil.ExtensionMethods
    {
        public static class SubSonicSqlQueryExtensionMethods
        {
            public static List<String> ExecuteTypedList(this SqlQuery qry)
            {
                List<String> list = new List<String>();
                foreach (System.Data.DataRow row in qry.ExecuteDataSet().Tables[0].Rows)
                {
                     list.Add((String)row[0]);
                }
                return list;
            }
        }
    }
    

Теперь добавьте ссылку на MyUtil.ExtensionMethods для вашего класса:

    using MyUtil.ExtensionMethods;

И, наконец, это работает:

    List<String> result = DB.Select(User.Columns.Name).From<User>().ExecuteTypedList();

Обратите внимание, что приведенный выше метод расширения перегружает метод ExecuteTypedList () без аргумента типа (к сожалению, этот фрагмент требует dotnet 3.5, но для меня это работает)

1 голос
/ 17 августа 2010

Я знаю, что опоздал на эту вечеринку, но нашел изящный способ «обмануть» эту проблему.

    List<String> result = 
  DB.Select()
    .From<Product>()
    .ExecuteTypedList<String>().Select(p => p.ProductName).ToList<String>();

Это работает как очарование для меня.

Надежда помогает кому-то где-то, так как я уверен, что вы далеко ушли от проблемы.

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

Не похоже, что SubSonic имеет надлежащую поддержку ExecuteTypedList со строковыми значениями. Метод, который строит список, сначала ищет тип SubSonic и, если нет совпадений, проверяет, является ли T типом значения. Поскольку строка не является типом значения, она переходит к последнему условию, которое пытается сопоставить имена свойств с возвращаемыми именами столбцов. Поскольку строка не имеет имени свойства, которое вы можете назначить, она завершается ошибкой.

См. Метод BuildTypedResult: http://subsonicproject.googlecode.com/svn/trunk/SubSonic/SqlQuery/SqlQuery.cs

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

Ну, я могу думать об этом, но это едва ли более элегантно:

List<string>result=DB.Select(Products.Columns.ProductName)
.From<Product>()
.ExecutTypedList<StringBuilder>()
.ConvertAll(sb=>sb.ToString());
...