лучший способ извлечь один ко многим отношениям с dapper dot net orm?
у меня есть два класса "Продукт" и "продавец".
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public Seller Seller { get; set; }
public int? SellerId { get; set; }
}
public class Seller
{
public int Id { get; set; }
public string Name { get; set; }
public List<Product> Products { get; set; }
}
Я хочу извлечь список продавцов со всеми их продуктами, используя dapper.
В настоящее время я делаю это так:
Dictionary<int, Seller> dic = new Dictionary<int, Seller>();
Conn.Query<Seller, Product, int>
(@"select s.*,p.* from Sellers s Join Products p
on p.SellerId = s.Id",
(s, p) => {
if (dic.ContainsKey(s.Id))
dic[s.Id].Products.Add(p);
else
{
s.Products = new List<Product>();
s.Products.Add(p);
dic.Add(s.Id, s);
}
return s.Id;
});
var sellers = dic.Select(pair => pair.Value);
есть ли лучший способ?
2 ответов
Я думаю, вы смешиваете, как вы хотите хранить данные с тем, как вы хотите его использовать. Я бы предложил нормализовать вашу базу данных.
//Normalized Database classes
public class Seller
{
public int Id { get; set; } // primary key
public string Name { get; set; }
}
public class Product
{
public int Id { get; set; } // primary key
public int SellerId { get; set; } // foreign key
public string Name { get; set; }
public decimal Price { get; set; }
}
после этого вы можете запросить таблицы продавца и продукта сразу.
var Sellers = connection.Query<Seller>("Select * from Seller");
var Products = connection.Query<Product>("Select * from Product");
затем используйте linq "group by", чтобы бросить продукт в словарь
var SellerWithProductsDict =
(from prod
in Products
group prod by prod.SellerId
into groupedProducts
select groupedProducts)
.ToDictionary(gp => gp.SellerId, gp => gp.ToList());
затем вы можете пройти через sellerwithproductsdict, чтобы увидеть все продукты продавца, и если вам нужно имя продавца, просто получите его по индексу от продавцов результат запроса
**************************************
Это конец ответа, но если вам действительно нужны продукты, смешанные с продавцами, вы можете использовать ту же структуру базы данных выше и сделать что-то вроде:
var qry = @"Select s.Id as SellerId,
s.Name as SellerName,
p.Id as ProductId,
p.Name as ProductName,
p.Price as ProductPrice
From Seller as s, Product as p
Where s.Id = p.id"
var SellerWithProducts = connection.Query(qry)
затем используйте функции linq "group by", чтобы бросить это в словарь. Я бы предложил посмотреть на это"Linq group-по нескольким полям" сообщение для помощи с группой по linq
мой последний пост почему-то сошел с ума.
во-первых, это может быть плохой идеей, чтобы получить все из вашей базы данных. Возможно, вы захотите ограничить свой запрос. Даже при том, что ваш стол сейчас может быть маленьким, вы не хотите прижиматься спиной к стене.
при этом я бы рекомендовал упростить код, чтобы получить продавцов и продукты, добавив статические методы на продавца и продукт.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int? SellerId { get; set; }
public Seller Seller { get; set; }
public static Product GetProductById(int id)
{
Product product = null;
using (SqlConnection connection = new SqlConnection("connectionString"))
{
product = connection.Query<Product>("select * from Product where Id = @Id", new { Id = id }).SingleOrDefault();
product.Seller = connection.Query<Seller>("select * from Seller where Id = @Id", new { Id = product.SellerId }).SingleOrDefault();
}
return product;
}
}
public class Seller
{
public int Id { get; set; }
public string Name { get; set; }
public List<Product> Products { get; set; }
public static Seller GetSellerById(int id)
{
Seller seller = null;
using (SqlConnection connection = new SqlConnection("connectionString"))
{
seller = connection.Query<Seller>("select * from Seller where Id = @Id", new { Id = id }).SingleOrDefault();
if(seller != null)
{
seller.Products = connection.Query<Product>("select * from Product where SellerId = @Id", new { Id = id }).ToList();
seller.Products.ForEach(p => p.Seller = seller);
}
}
return seller;
}
}
имейте в виду, это грубо и не представляет все, что вам может понадобиться, но его проще использовать в долгосрочной перспективе и лучше следовать объектно-ориентированному дизайну, чем делать один из запросов для получения ваших данных.
вы можете дополнительно расширить эту идею, добавив методы, которые запрашивают другие вещи о продавце или продукте, такие как GetSellersInZipCode(int zipCode) и возвращают список с помощью этого метода.