我在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();
,因为传递给映射函数的cat
是null
。
我还将此方法添加到Assert类:
public static void IsNotNull(this object obj)
{
if (obj == null)
{
throw new ApplicationException("Expected not null");
}
}
答案 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)
答案 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,...'