Dapper MultiMap不适用于具有NULL值的splitOn

时间:2012-05-24 20:21:50

标签: dapper

我在dapper中尝试拆分包含NULL的列时出现MultiMaps问题。 Dapper似乎没有实例化对象,我的映射函数接收null而不是对象。

这是我的新测试:

    class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public Category Category { get; set; }
    }
    class Category
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    }
    public void TestMultiMapWithSplitWithNullValue()
    {
        var sql = @"select 1 as id, 'abc' as name, NULL as description, 'def' as name";
        var product = connection.Query<Product, Category, Product>(sql, (prod, cat) =>
        {
            prod.Category = cat;
            return prod;
        }, splitOn: "description").First();
        // assertions
        product.Id.IsEqualTo(1);
        product.Name.IsEqualTo("abc");
        product.Category.IsNotNull();
        product.Category.Id.IsEqualTo(0);
        product.Category.Name.IsEqualTo("def");
        product.Category.Description.IsNull();
    }

失败的行是product.Category.IsNotNull();,因为传递给映射函数的catnull

我还将此方法添加到Assert类:

public static void IsNotNull(this object obj)
{
    if (obj == null)
    {
        throw new ApplicationException("Expected not null");
    }
}

3 个答案:

答案 0 :(得分:18)

这是“按设计”,但我可以再次访问它。

特别是这种行为有助于左连接。以此为例:

cnn.Query<Car,Driver>("select * from Cars c left join Drivers on c.Id = CarId",
   (c,d) => {c.Driver = d; return c;}) 

麻烦的是,如果我们允许“覆盖”创建Driver对象,则每个Car将会有Driver偶数连接失败。

为了解决这个问题,我们可以扫描整个被拆分的段,并确保在映射NULL对象之前所有值都是NULL。这将对多映射器产生非常小的性能影响。

要解决您的案例,您可以插入代理列:

var sql = @"select 1 as id, 'abc' as name, '' as split, 
            NULL as description, 'def' as name";
    var product = connection.Query<Product, Category, Product>(sql, (prod, cat) =>
    {
        prod.Category = cat;
        return prod;
    }, splitOn: "split").First();

答案 1 :(得分:1)

对于所有想要可视化的人:

Dapper按最后一个相等的列名分割:

enter image description here

让我们交换列的位置:

enter image description here

null问题:

enter image description here

交换列null:

enter image description here

斯普利森救援:

enter image description here

答案 2 :(得分:0)

我遇到了同样的问题,我被迫选择一个假的“拆分”列以使Dapper填充我的对象,而不是仅仅将其null;

我的解决方法:

    string req = @"
SELECT
    T1.a as PropA,
    T1.b as PropB,

    1 as Split,
    T2.a as PropA,
    T2.b as PropB,

    1 as Split,
    ...
FROM
    xxx T1,
    yyy T2,
    ...";
    using (var db = new OracleConnection(...))
    {
        return db.Query(
            req,
            (T1, T2) => {
                ...
            },
            splitOn:'Split,Split,...');
    }

Dapper应该可以选择避免使用splitOn:'Split,Split,...'