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

然後你可以循環通過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-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
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因