StackService动态DTO

时间:2014-05-28 12:09:48

标签: c# servicestack ormlite-servicestack

我正在尝试创建一个用于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

如果要返回的五个项目,结果如下:     [{},{},{},{},{}]

我也试过使用字典,但也没有用,似乎我可能误解了这一点,因此我不需要再详细说明了。

感谢任何帮助。

谢谢, 约翰

1 个答案:

答案 0 :(得分:2)

将POCO类1:1映射到RDBMS表

您要实现的目标违背了ORM的目标,例如OrmLite,它旨在与已知类型和POCO 一起使用。从official documentation开始,OrmLite的一个主要目标是:

  

按惯例将POCO类1:1映射到RDBMS表,不需要任何属性。

使用object

如果您提供简单的object作为您的类型,即。 db.Query<object> ,那么该对象没有公共属性可以反映返回的查询数据,因此您得到[{},{},{},{},{}]

的NoSQL?

这看起来不适合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响应:

Data Screenshot

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
    }
}]