beste Möglichkeit, eine eins zu viele Beziehung mit dapper dot net orm zu extrahieren?

c# dapper one-to-many orm

Frage

Ich habe zwei Klassen "Produkt" und "Verkäufer".

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

Ich möchte eine Liste der Verkäufer mit all ihren Produkten mit Dapper extrahieren.

Momentan mache ich es so:

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

Gibt es einen besseren Weg?

Akzeptierte Antwort

Ich denke, Sie mischen, wie Sie die Daten speichern möchten, wie Sie sie verwenden möchten. Ich würde vorschlagen, Ihre Datenbank zu normalisieren.

//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; }
}

Dann können Sie die Verkäufer- und Produkttabellen direkt abfragen.

var Sellers = connection.Query<Seller>("Select * from Seller");
var Products = connection.Query<Product>("Select * from Product");

Dann benutze linq "group by" um Product in ein Dictionary zu werfen

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

Dann können Sie das SellerWithProductsDict durchlaufen, um alle Verkäuferprodukte zu sehen, und wenn Sie den Verkäufernamen benötigen, holen Sie ihn einfach durch Index vom Suchergebnis der Verkäufer

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

Das ist das Ende der Antwort, aber wenn Sie wirklich die Produkte mit den Verkäufern gemischt brauchen, können Sie die gleiche Datenbankstruktur oben verwenden und tun Sie etwas wie:

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)

Dann benutze linq "group by" -Funktionen, um das in ein Dictionary zu werfen. Ich würde vorschlagen, diesen Beitrag " Linq Group-by multiple fields " für Hilfe mit der Gruppe von linq zu suchen


Beliebte Antwort

Mein letzter Beitrag ist aus irgendeinem Grund verrückt geworden.

Zunächst einmal könnte es eine schlechte Idee sein, alles aus Ihrer Datenbank zu bekommen. Möglicherweise möchten Sie Ihre Suchanfrage einschränken. Auch wenn Ihr Tisch jetzt vielleicht klein ist, möchten Sie sich nicht gegen eine Wand wehren.

Nachdem das gesagt wurde, würde ich empfehlen, den Code zu vereinfachen, um die Verkäufer und Produkte zu erhalten, indem statische Methoden zu Verkäufer und Produkt hinzugefügt werden.

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

Beachten Sie, dass dies grob ist und nicht alles darstellt, was Sie benötigen, aber es ist auf lange Sicht einfacher zu benutzen und folgt objektorientiertem Design besser als eine Abfrage zu machen, um Ihre Daten zu erhalten.

Sie können diese Idee weiter erweitern, indem Sie Methoden hinzufügen, die andere Dinge zum Verkäufer oder Produkt wie GetSellersInZipCode (int zipCode) abfragen und eine Liste über diese Methode zurückgeben.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum