使用Dapper.net进行多映射查询时出现意外行为

mar*_*nes 5 c# asp.net mapping dapper

我刚刚开始关注Dapper.net并且刚刚尝试了一些不同的查询,其中一个产生了我不希望的奇怪结果.

我有2张桌子 - Photos&PhotoCategories,其中有关系CategoryID

照片表

PhotoId (PK - int)  
CategoryId (FK - smallint)  
UserId (int)
Run Code Online (Sandbox Code Playgroud)

PhotoCategories表

CategoryId (PK - smallint)  
CategoryName (nvarchar(50))
Run Code Online (Sandbox Code Playgroud)

我的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; }
{
Run Code Online (Sandbox Code Playgroud)

我想使用多映射来返回一个实例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();
Run Code Online (Sandbox Code Playgroud)

执行此操作时,并非所有属性都已填充(尽管DB表和我的对象之间的名称相同.

我注意到如果我don't选择p.*等' 在我的SQL,而不是.

我明确说明了这些字段.

我想EXCLUDING p.CategoryId从查询返回,然后所有内容都被填充(显然除了我从select语句中排除的Photo对象的CategoryId).

但我希望能够在查询中包含该字段,并将其与在其中查询的所有其他字段SQL一起填充.

我可以CategoryId从我的Photo类中排除属性,并Photo.PhotoCategory.CategoryId在我需要ID时始终使用.

但在某些情况下,PhotoCategory当我得到Photo对象的实例时,我可能不想填充该对象.

有谁知道上述行为发生的原因?这对Dapper来说是正常的吗?

Sam*_*ron 5

我刚刚为此做了一个修复:

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

    }
Run Code Online (Sandbox Code Playgroud)

如果类型中有一个字段,那么多映射器就会变得混乱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它会拆分,从而产生预期的结果.