我正在尝试创建一个用于ServiceStack的动态DTO。原因是在不知道返回的列数的情况下从数据库中查询数据,因此无法创建正常的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
如果要返回的五个项目,结果如下: [{},{},{},{},{}]
我也试过使用字典,但也没有用,似乎我可能误解了这一点,因此我不需要再详细说明了。
感谢任何帮助。
谢谢, 约翰
答案 0 :(得分:2)
您要实现的目标违背了ORM的目标,例如OrmLite,它旨在与已知类型和POCO 一起使用。从official documentation开始,OrmLite的一个主要目标是:
按惯例将POCO类1:1映射到RDBMS表,不需要任何属性。
object
如果您提供简单的object
作为您的类型,即。 db.Query<object>
,那么该对象没有公共属性可以反映返回的查询数据,因此您得到[{},{},{},{},{}]
。
这看起来不适合ORM,甚至可能不适合关系数据库。查询RDBMS表并且不知道它将返回的列是不寻常的。这看起来像NoSQL territory,您需要一个数据结构。
您的问题最终在于在数据库中创建数据的轴,因为这是创建动态列。如果您返回订单列表并在代码中执行了透视,则可以轻松解决问题。
因此,如果您创建了一个表示订单表的对象:
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
}
}]