了解Dapper splitOn

时间:2018-09-11 14:06:16

标签: c# dapper

我得到一个意外的结果,显示带有正确项目列表的预期结果之后的产品列表为空的产品。只有包含多个项目的产品才发生这种情况。有谁知道如何为Dapper编写代码?

这是我的测试代码:

    public IEnumerable<Customer> Test2()
    {
        var query = @"select cast(1 as int) CustomerId, 'name' CustomerName,cast(1 as int) CustomerId, cast(1 as int) ProductId, 'a' ProductName, 'x' AccountOpened, cast(1 as int) ProductId, cast(1 as int) ItemId, 'a' ItemName
UNION
select cast(1 as int) CustomerId, 'name' CustomerName,cast(1 as int) CustomerId, cast(1 as int) ProductId, 'a' ProductName, 'x' AccountOpened, cast(1 as int) ProductId, cast(2 as int) ItemId, 'b' ItemName
UNION
select cast(1 as int) CustomerId, 'name' CustomerName, cast(1 as int) CustomerId, cast(2 as int) ProductId, 'b' ProductName, 'x' AccountOpened, cast(2 as int) ProductId, cast(3 as int) ItemId, 'b' ItemName
UNION
select cast(2 as int) CustomerId, 'name1' CustomerName, cast(2 as int) CustomerId, cast(1 as int) ProductId, 'a' ProductName, 'x' AccountOpened, cast(1 as int) ProductId, cast(1 as int) ItemId, 'a' ItemName
UNION
select cast(2 as int) CustomerId, 'name1' CustomerName, cast(2 as int) CustomerId, cast(1 as int) ProductId, 'a' ProductName, 'x' AccountOpened, cast(1 as int) ProductId, cast(2 as int) ItemId, 'b' ItemName
UNION
select cast(2 as int) CustomerId, 'name1' CustomerName, cast(2 as int) CustomerId, cast(2 as int) ProductId, 'b' ProductName, 'x' AccountOpened, cast(2 as int) ProductId, cast(3 as int) ItemId, 'b' ItemName
UNION
select cast(2 as int) CustomerId, 'name1' CustomerName, cast(2 as int) CustomerId, cast(3 as int) ProductId, 'c' ProductName, 'x' AccountOpened, cast(3 as int) ProductId, cast(4 as int) ItemId, 'c' ItemName";
        var lookup = new Dictionary<int, Customer>();
        DbConnection.Query<Customer, Product, Item, Customer>(query, (c, p, i) =>
        {
            if (!lookup.TryGetValue(c.CustomerId, out var cust))
                lookup.Add(c.CustomerId, cust = c);
            if (cust.Products == null)
                cust.Products = new List<Product>();
            var product = p;
            if (cust.Products.Exists(prod => prod.ProductId == p.ProductId))
            {
                product = cust.Products.Find(prod => prod.ProductId == p.ProductId);
            }
            cust.Products.Add(p);
            if (product.Items == null)
                product.Items = new List<Item>();
            product.Items.Add(i);
            return cust;
        }, splitOn: "CustomerId,ProductId");
        return lookup.Values;
    }

    public class Customer
    {
        public int CustomerId { get; set; }
        public string CustomerName { get; set; }
        public List<Product> Products { get;set; }
    }
    public class Product
    {
        public int ProductId { get; set; }
        public string ProductName { get; set; }
        public string AccountOpened { get; set; }
        public List<Item> Items { get; set; }
        //public int CustomerId { get; set; }
    }
    public class Item
    {
        public int ItemId { get; set; }
        public string ItemName { get; set; }
        //public int ProductId { get; set; }
    }

这是我返回的JSON格式的响应:

[
  {
    "customerId": 1,
    "customerName": "name",
    "products": [
      {
        "productId": 1,
        "productName": "a",
        "accountOpened": "x",
        "items": [
          {
            "itemId": 1,
            "itemName": "a"
          },
          {
            "itemId": 2,
            "itemName": "b"
          }
        ]
      },
      {
        "productId": 1,
        "productName": "a",
        "accountOpened": "x",
        "items": null
      },
      {
        "productId": 2,
        "productName": "b",
        "accountOpened": "x",
        "items": [
          {
            "itemId": 3,
            "itemName": "b"
          }
        ]
      }
    ]
  },
  {
    "customerId": 2,
    "customerName": "name1",
    "products": [
      {
        "productId": 1,
        "productName": "a",
        "accountOpened": "x",
        "items": [
          {
            "itemId": 1,
            "itemName": "a"
          },
          {
            "itemId": 2,
            "itemName": "b"
          }
        ]
      },
      {
        "productId": 1,
        "productName": "a",
        "accountOpened": "x",
        "items": null
      },
      {
        "productId": 2,
        "productName": "b",
        "accountOpened": "x",
        "items": [
          {
            "itemId": 3,
            "itemName": "b"
          }
        ]
      },
      {
        "productId": 3,
        "productName": "c",
        "accountOpened": "x",
        "items": [
          {
            "itemId": 4,
            "itemName": "c"
          }
        ]
      }
    ]
  }
]

3 个答案:

答案 0 :(得分:0)

我发现问题是您在查询中使用产品。

这可能会帮助

var product = p;
if (cust.Products.Exists(prod => prod.ProductId == p.ProductId))
{
   product = cust.Products.Find(prod => prod.ProductId == p.ProductId);
}
else
{
   cust.Products.Add(p);
}

if (product.Items == null)
   product.Items = new List<Item>();
product.Items.Add(i);

答案 1 :(得分:0)

这是我为修复代码所做的更改:

        var product = p;
        if (cust.Products.Exists(prod => prod.ProductId == p.ProductId))
        {
            product = cust.Products.Find(prod => prod.ProductId == p.ProductId);
        }
        cust.Products.Add(p);

对此

        var product = cust.Products.FirstOrDefault(prod => prod.ProductId == p.ProductId);
        if (product == null)
            cust.Products.Add(product = p);

答案 2 :(得分:0)

问题在于您的查询,每个ProductId应该具有相同的商品列表

您的查询应该是

SELECT * FROM Customer c 
INNER JOIN Product p ON c.CustomerId = p.CustomerId
INNER JOIN Item i ON i.ProductId = p.ProductId

您的Dapper查询就像

var cust = DbConnection.Query<Customer, Product, Item, Customer>(query, (c, p, i) =>
    {
        c.Products.Add(p);
        p.Items.Add(i);

        return c;
    }, splitOn: "ProductId,ItemId");
return cust;

如果列表为空,则可能需要初始化。