了解Dapper splitOn

问题描述 投票:0回答:3

我收到一个意外的结果,显示带有空项目列表的产品,其中包含正确项目列表的预期结果。只有包含多个项目的产品才会发生这种情况。有谁知道如何为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"
          }
        ]
      }
    ]
  }
]
c# dapper
3个回答
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);

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);

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;

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

© www.soinside.com 2019 - 2024. All rights reserved.