【问题标题】:Dapper One-To-Many with multiple tables具有多个表的 Dapper 一对多
【发布时间】:2018-06-11 22:37:18
【问题描述】:

我让 Dapper 像这样检索我的数据:

using (var dbConnection = new SqlConnection(_connectionString))
{
    const string sql =
                "SELECT Offers.*, " +
                "       OfferDetails.*," +
                "       SomeLookup.Id AS SomeLookupId, SomeLookup.* " +
                "FROM   Offers " +
                "INNER JOIN OfferBets ON Offers.Id = OfferBets.OfferId " +
                "INNER JOIN SomeLookup ON SomeLookup.Id = Offers.SomeLookupId";

   dbConnection.Open();

   var betDictionary = new Dictionary<int, Offer>();

   return await dbConnection.QueryAsync<Offer, OfferBet, SomeLookup, Offer>(
                sql,
                (offer, bet, someLookup) =>
                {
                    if (!betDictionary.TryGetValue(offer.Id, out var offerEntry))
                    {
                        offerEntry = offer;
                        offerEntry.SomeLookup = someLookup;
                        offerEntry.Bets = new List<OfferBet>();
                        betDictionary.Add(offer.Id, offerEntry);
                    }

                    offerEntry.Bets.Add(bet);

                    return offerEntry;
                },
                splitOn: "OfferId, SomeLookupId"
            );
    }
}

它应该返回一个 Offer 列表,每个 Offer 都包含一个 OfferDetails 列表和一个 SomeLookup。

我得到的是每个 OrderDetails 对象的订单列表。它正在返回连接的数据集并为每条记录填充一个订单(并且每个记录在集合中都有 1 个 OrderDetails 项)。

我在重复检测中做错了什么?

【问题讨论】:

    标签: .net dapper


    【解决方案1】:

    我假设 OfferDetails / OfferBets 除了 OfferId 之外还包含一个名为 Id 的列,并且此列放置在 OfferId 这搞混了。因此,如果您将 splitOn 参数更改为 splitOn: "Id, SomeLookupId" 它可能会起作用。

    [Test]
    public void tstAbc()
    {
        using (var dbConnection = new SqlConnection(_connectionString))
        {
            const string sql = @"WITH Offers AS (
    
                                     SELECT * FROM (
                                         VALUES (1, 1), (2, 1), (3, 2)
                                         ) AS a (Id, SomeLookupId)
                                 ),
    
                                 OfferBets AS (
    
                                     SELECT * FROM (
                                         VALUES
                                             (1, 1), (2, 1), (3, 2), (4, 3)
                                         ) AS a (Id, OfferId)
    
                                 ),
    
                                 SomeLookup AS (
    
                                     SELECT * FROM (
                                         VALUES
                                             (1), (2), (3)
                                         ) AS a (Id)
    
                                 )
    
                                 SELECT Offers.*,
                                        OfferBets.*,
                                        SomeLookup.Id AS SomeLookupId, SomeLookup.*
                                 FROM   Offers
                                 INNER JOIN OfferBets ON Offers.Id = OfferBets.OfferId
                                 INNER JOIN SomeLookup ON SomeLookup.Id = Offers.SomeLookupId";
    
            dbConnection.Open();
    
            var betDictionary = new Dictionary<int, Offer>();
    
            var res = dbConnection.Query<Offer, OfferBet, SomeLookup, Offer>(
                sql,
                (offer, bet, someLookup) =>
                {
                    if (!betDictionary.TryGetValue(offer.Id, out var offerEntry))
                    {
                        offerEntry = offer;
                        offerEntry.Bets = new List<OfferBet>();
                        betDictionary.Add(offer.Id, offerEntry);
                    }
    
                    offerEntry.Bets.Add(bet);
                    offerEntry.SomeLookup = someLookup;
    
                    return offerEntry;
                },
                splitOn: "Id, SomeLookupId"
            );
        }
    }
    

    【讨论】:

    • OfferBet.Id 字段的好位置,只需在 OfferBets.* 之前添加 OfferBets.Id As OfferBetId 然后拆分,我现在可以在优惠对象中获得所有正确的投注。
    【解决方案2】:

    这里的答案是给 OfferDetails 的 ID 字段加上别名,然后在上面拆分,所以 SQL 看起来像

    SELECT Offers.*,
           OfferDetails.Id AS OfferDetailId, OfferDetails.*,
           SomeLookup.Id AS SomeLookupId, SomeLookup.*
    FROM   Offers
    INNER JOIN OfferDetails ON Offers.Id = OfferDetails.OfferId
    INNER JOIN SomeLookup ON SomeLookup.Id = Offers.SomeLookupId"
    

    那么 splitOn 部分看起来像

    splitOn: "OfferBetId, SomeLookupId",
    

    这会在Offers 中留下重复项,因此我们还需要对结果执行.Distinct()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 2012-06-15
      • 2015-07-15
      • 2021-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多