Понимание Dapper splitOn - PullRequest
       9

Понимание Dapper splitOn

0 голосов
/ 11 сентября 2018

Я получаю неожиданный результат, показывая Продукты с пустым списком Товаров после ожидаемого результата с правильным списком Товаров. Это происходит только для Продукта, который содержит несколько элементов. Кто-нибудь знает, как закодировать это для 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 голосов
/ 11 сентября 2018

Это то, что я изменил, чтобы исправить код:

        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 голосов
/ 11 сентября 2018

Проблема в вашем запросе, у каждого 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;

Вам может понадобиться инициализировать ваши списки, если они нулевые.

0 голосов
/ 11 сентября 2018

Я вижу, что проблема в том, что вы работаете с продуктами в запросе.

Это может помочь

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