简体   繁体   English

StackService动态DTO

[英]StackService dynamic DTO

I'm trying to create a dynamic DTO for use in ServiceStack. 我正在尝试创建一个动态DTO以在ServiceStack中使用。 The reason is that data is queried from the database without knowing the number of columns returned and therefore no way to create a normal dto. 原因是在不知道返回的列数的情况下从数据库查询数据,因此无法创建正常的dto。

UPDATE: The reason for not knowing the number of columns is that a pivot is used to return the data. 更新:不知道列数的原因是枢轴用于返回数据。 Quite simply turning this: 很简单地将其转换为:

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

into this. 到这个。

CustID  | Jan- 2008 | Feb- 2008 | Mar - 2008 |
1       | 100       | 350       |  250
2       | 200       | 221       | 2150

the user will be able to specify the start and end date and thus determine the number of columns in the result. 用户将能够指定开始和结束日期,从而确定结果中的列数。

UPDATE END 更新结束

My code: 我的代码:

DTO 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 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

If five items where to be returned this is what the result looks like: [{},{},{},{},{}] 如果要返回五个项目,结果将是这样:[{},{},{},{},{}]

I have tried using a dictionary as well but that did not work either, it seems I might have misunderstood that and thus will not elaborate as I need to read some more. 我也尝试过使用字典,但是也没有用,似乎我可能会误解了这一点,因此由于需要阅读更多内容,因此不再赘述。

Any help is appreciated. 任何帮助表示赞赏。

Thanks, Johann 谢谢,约翰

Map a POCO class 1:1 to an RDBMS table 将POCO类1:1映射到RDBMS表

What you are trying to achieve goes against the aims of an ORM, such as OrmLite, which is designed to work with known types and POCOs . 您试图实现的目标违反了ORM的目标,例如OrmLite,该目标旨在与已知类型和POCO一起使用 From the official documentation , a key aim of OrmLite is to: 根据官方文档 ,OrmLite的主要目标是:

Map a POCO class 1:1 to an RDBMS table, cleanly by conventions, without any attributes required. 按照惯例,将POCO类1:1映射到RDBMS表,无需任何属性。

Use of object 使用object

If you provide a plain object as your type ie db.Query<object> , then there are no public properties of that object to reflect the returned query data into hence you get [{},{},{},{},{}] . 如果您提供一个普通object作为类型, db.Query<object> ,则该对象没有公共属性可将返回的查询数据反映到其中,因此您将获得[{},{},{},{},{}]

NoSQL? NoSQL的?

This doesn't look like a good fit for an ORM, and perhaps not even a relational database. 这看起来不太适合ORM,甚至可能不适合关系数据库。 It's unusual to query a RDBMS table and not know the columns it will return. 查询RDBMS表并且不知道它将返回的列是不寻常的。 This looks like NoSQL territory , where you need a data structure. 这看起来像NoSQL领土 ,您需要一个数据结构。


Pivot the data in your business logic: 在您的业务逻辑中透视数据:

Your issue lies ultimately in creating the pivot of your data in the database, because this is creating dynamic columns. 您的问题最终在于在数据库中创建数据的枢轴,因为这是在创建动态列。 The problem can be easily solved if you returned the list of orders and performed the pivot in your code. 如果返回订单列表并在代码中执行数据透视,则可以轻松解决该问题。

So if you created an object to represent the order table: 因此,如果您创建了一个代表订单表的对象:

public class Order
{
    public int CustID { get; set; }
    public DateTime OrderDate { get; set; }
    public int Qty { get; set; }
}

Then you can query the database for a List<Order> and then pivot that data into a suitable DTO, such as: 然后,您可以在数据库中查询List<Order> ,然后将数据透视到合适的DTO中,例如:

public class CustomerMonthlyOrders
{
    public int CustID { get; set; }
    public Dictionary<string, int> QuantitiesOrdered { get; set; }
}

So given a route: 因此给定一条路线:

[Route("/orders", "GET")]
public class GetOrderHistoryRequest : IReturn<List<CustomerMonthlyOrders>>
{
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}

Your service can pivot the data: Note: the SQL is untested, and will need tweaked to your database. 您的服务可以透视数据: 注意: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;
    }
}

This then creates the dynamic DTO response you are looking for: 然后,这将创建您要查找的动态DTO响应:

数据截图

JSON produced: 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
    }
}]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM