лучший способ извлечь один из многих отношений с dapper dot net orm?

c# dapper one-to-many 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);

Есть ли лучший способ?

Принятый ответ

Я думаю, вы смешиваете, как вы хотите хранить данные, как вы хотите их использовать. Я бы предложил нормализовать вашу базу данных.

//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», чтобы загрузить Product в словарь

var SellerWithProductsDict = 
        (from prod
        in Products 
        group prod by prod.SellerId
        into groupedProducts
        select groupedProducts)
        .ToDictionary(gp => gp.SellerId, gp => gp.ToList());

Затем вы можете пройти через SalesWithProductsDict, чтобы просмотреть все продукты продавца, и если вам нужно имя продавца, просто получите его по индексу из результата запроса Sellers

**************************************

Это конец ответа, но если вам действительно нужны продукты, смешанные с продавцами, вы можете использовать одну и ту же структуру базы данных выше и сделать что-то вроде:

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-by multiple fields » для помощи с группой 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), и возвращают List с помощью этого метода.



Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему