Я пытаюсь создать динамический DTO для использования в ServiceStack. Причина в том, что данные запрашиваются из базы данных, не зная количества возвращенных столбцов и, следовательно, не могут создать нормальное dto.
ОБНОВЛЕНИЕ: причина не знать количество столбцов заключается в том, что для возврата данных используется стержень. Достаточно просто:
CustID | OrderDate | Qty
1 | 1/1/2008 | 100
2 | 1/2/2008 | 200
1 | 2/2/2008 | 350
2 | 2/28/2008 | 221
1 | 3/12/2008 | 250
2 | 3/15/2008 | 2150
в это.
CustID | Jan- 2008 | Feb- 2008 | Mar - 2008 |
1 | 100 | 350 | 250
2 | 200 | 221 | 2150
пользователь сможет указать дату начала и окончания и, следовательно, определить количество столбцов в результате.
ОБНОВЛЕНИЕ КОНЕЦ
Мой код:
DTO
public class Rep_DataAvailibility
{
public DateTime startDate { get; set; }
public DateTime endDate { get; set; }
}
public static class Rep_DataAvailibilityData
{
private static string _commandText = "select name,description,Constant from measurement"; // used as a test
public static object GetData(Rep_DataAvailibility parameters)
{
object result = new object();
using (IDbConnection db = DataHelper.DbProvider.OpenDbConnection())
{
result = db.Query<object>(_commandText).ToArray();
}
return result;
}
}
API
public partial class Rep_DataAvailibilityService : Service
{
//[Authenticate]
public object Get(Rep_DataAvailibility request)
{
return Rep_DataAvailibilityData.GetData(request);
} //end of GET endpoint
}//end of service class
Если пять элементов, куда нужно вернуть, это результат: [{}, {}, {}, {}, {}]
Я тоже пробовал использовать словарь, но это тоже не сработало, кажется, я, возможно, неправильно понял это и поэтому не буду подробно излагать, поскольку мне нужно еще кое-что прочитать.
Любая помощь приветствуется.
Спасибо, Иоганн
То, что вы пытаетесь достичь, противоречит целям ORM, таким как OrmLite, который предназначен для работы с известными типами и POCOs. Из официальной документации основная цель OrmLite заключается в следующем:
Сопоставьте класс POCO 1:1 с таблицей РСУБД, чисто по соглашениям, без каких-либо атрибутов.
object
Если вы предоставляете простой object
качестве своего типа, то есть db.Query<object>
, тогда нет никаких публичных свойств этого объекта, чтобы отражать возвращаемые данные запроса, поэтому вы получаете [{},{},{},{},{}]
.
Это не похоже на хорошую совместимость с ORM и, возможно, даже с реляционной базой данных. Необычно запрашивать таблицу RDBMS и не знать столбцы, которые она вернет. Это похоже на территорию NoSQL, где вам нужна структура данных.
Ваша проблема в конечном счете заключается в создании стержня ваших данных в базе данных, потому что это создает динамические столбцы. Проблема может быть легко решена, если вы вернули список заказов и выполнили опорный пункт в своем коде.
Поэтому, если вы создали объект для представления таблицы заказов:
public class Order
{
public int CustID { get; set; }
public DateTime OrderDate { get; set; }
public int Qty { get; set; }
}
Затем вы можете запросить базу данных для List<Order>
а затем повернуть эти данные в подходящий DTO, например:
public class CustomerMonthlyOrders
{
public int CustID { get; set; }
public Dictionary<string, int> QuantitiesOrdered { get; set; }
}
Поэтому, учитывая маршрут:
[Route("/orders", "GET")]
public class GetOrderHistoryRequest : IReturn<List<CustomerMonthlyOrders>>
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
Ваша служба может сворачивать данные: Примечание: SQL не проверен и нуждается в настройке в вашу базу данных.
public class OrderService : Service
{
public List<CustomerMonthlyOrders> Get(GetOrderHistoryRequest request)
{
// Perform the query to get all orders within the range
// (NOTE: SQL is untested, and will need tweaked to your db)
List<Order> allOrders = Db.SqlList<Order>("SELECT * FROM Orders WHERE OrderDate >= @Start AND OrderDate < @End", new {
Start = request.StartDate,
End = request.EndDate
});
// Prepare response object
var customerMonthlyOrders = new List<CustomerMonthlyOrders>();
// Get the distinct customer Ids
var customers = orders.Select(o => o.CustID).OrderBy(o => o).Distinct();
foreach(var custId in customers)
{
// Create a result for the customer
var result = new CustomerMonthlyOrders {
CustID = custId,
QuantitiesOrdered = new Dictionary<string, int>()
};
// Get the customers relevant orders
var orders = allOrders.Where(o => o.CustID == custId);
foreach(var order in orders)
{
// Determine the month the order belongs to (i.e. the key)
var month = order.OrderDate.ToString("MMM-yyyy");
// Add or update the quantities
if(result.QuantitiesOrdered.ContainsKey(month))
result.QuantitiesOrdered[month] += order.Qty;
else
result.QuantitiesOrdered.Add(month, order.Qty);
}
// Add the customers order to the results
customerMonthlyOrders.Add(result);
}
// Return the results
return customerMonthlyOrders;
}
}
Затем создается динамический ответ DTO, который вы ищете:
JSON выпустил:
[{
"CustID": 1,
"QuantitiesOrdered": {
"Jan-2008": 100,
"Feb-2008": 350,
"Mar-2008": 250
}
}, {
"CustID": 2,
"QuantitiesOrdered": {
"Jan-2008": 200,
"Feb-2008": 221,
"Mar-2008": 2150
}
}]