使用Dapper.net進行多映射查詢時出現意外行為

asp.net c# dapper mapping

我剛剛開始關注Dapper.net並且剛剛嘗試了一些不同的查詢,其中一個產生了我不希望的奇怪結果。

我有2個表 - PhotosPhotos PhotoCategories ,其中與CategoryID有關

照片表

PhotoId (PK - int)  
CategoryId (FK - smallint)  
UserId (int)

PhotoCategories表

CategoryId (PK - smallint)  
CategoryName (nvarchar(50))

我的2個班:

public class Photo
{
    public int PhotoId { get; set; }
    public short CategoryId { get; set; }
    public int UserId { get; set; }
    public PhotoCategory PhotoCategory { get; set; }
}

public class PhotoCategory
{
    public short CategoryId { get; set; }
    public string CategoryName { get; set; }
{

我想使用多映射來返回Photo的實例,其中包含相關PhotoCategory的填充實例。

var sql = @"select p.*, c.* from Photos p inner 
            join PhotoCategories c 
            on p.CategoryID = c.CategoryID where p.PhotoID = @pid";

cn.Open();
var myPhoto = cn.Query<Photo, PhotoCategory, Photo>(sql, 
               (photo, photoCategory) => { photo.PhotoCategory = photoCategory; 
                                           return photo; }, 
               new { pid = photoID }, null, true, splitOn: "CategoryID").Single();

執行此操作時,並不是所有屬性都會被填充(儘管數據庫表和我的對象之間的名稱相同。

我注意到如果我don't '選擇p。*等'在我的SQL ,而是。

我明確說明了這些字段。

我想從查詢中返回EXCLUDING p.CategoryId ,然後填充所有內容(顯然除了我從select語句中排除的Photo對象的CategoryId)。

但我希望能夠在查詢中包含該字段,並將其與SQL查詢的所有其他字段一起填充。

我可以從Photo類中排除CategoryId屬性,並在需要ID時始終使用Photo.PhotoCategory.CategoryId

但在某些情況下,當我得到Photo對象的實例時,我可能不想填充PhotoCategory對象。

有誰知道上述行為發生的原因?這對Dapper來說是正常的嗎?

一般承認的答案

我剛剛為此做了一個修復:

    class Foo1 
    {
        public int Id;
        public int BarId { get; set; }
    }

    class Bar1
    {
        public int BarId;
        public string Name { get; set; }
    }

    public void TestMultiMapperIsNotConfusedWithUnorderedCols()
    {

        var result = connection.Query<Foo1,Bar1,
                      Tuple<Foo1,Bar1>>(
                         "select 1 as Id, 2 as BarId, 3 as BarId, 'a' as Name",
                         (f,b) => Tuple.Create(f,b), splitOn: "BarId")
                         .First();

        result.Item1.Id.IsEqualTo(1);
        result.Item1.BarId.IsEqualTo(2);
        result.Item2.BarId.IsEqualTo(3);
        result.Item2.Name.IsEqualTo("a");

    }

如果在第first類型中存在一個字段,那麼多映射器會變得混亂,這也恰好是在second類型中...... AND ...被用作分裂點。

為了克服現在的小巧,允許Id字段顯示在第一種類型的任何地方。為了顯示。

說我們有:

classes: A{Id,FooId} B{FooId,Name}
splitOn: "FooId"
data: Id, FooId, FooId, Name

舊的拆分方法沒有考慮它映射的實際底層類型。所以...它映射了Id => AFooId, FooId, Name => B

這種新方法是知道的道具和領域的A 。當它第一次遇到流中的FooId時,它不會啟動拆分,因為它知道A有一個名為FooId的屬性需要映射,下次看到FooId它會分裂,從而產生預期的結果。


熱門答案

我知道這個問題已經過時了,但我想我會在2分鐘內找到明顯的答案:只需在一個表中使用一個id:

即:

SELECT
    user.Name, user.Email, user.AddressId As id, address.*
FROM 
    User user
    Join Address address
    ON user.AddressId = address.AddressId


許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因