使用下面的示例代码作为上下文...当我运行此查询时,我得到了' Id'字段返回默认值(对于int为0)。我想告诉dapper以一种方式运行,如果结果集中有一列没有映射到我的结果对象上的属性,它将抛出异常。 (我知道问题只是我需要删除SQL查询中的额外内容,但我有兴趣让它更明确地暴露自己)
我一直无法找到有关此主题的任何内容。如果Dapper甚至可以这样做,请告诉我。
提前致谢(除了这个问题,对于那些没有采取过任何措施的人来说,Dapper真的是切片面包以来最棒的东西!)。
class CustomerRecord
{
public int Id { get; set; }
public string Name { get; set; }
}
CustomerRecord[] GetCustomerRecords()
{
CustomerRecord[] ret;
var sql = @"SELECT
CustomerRecordId AS Idd,
CustomerName as Name
FROM CustomerRecord";
using (var connection = new SqlConnection(this.connectionString))
{
ret = connection.Query<CustomerRecord>(sql).ToArray();
}
return ret;
}
答案 0 :(得分:4)
您可以使用Dapper的DefaultTypeMap
创建自己的类型映射,并在找不到该成员时抛出异常:
public class ThrowWhenNullTypeMap<T> : SqlMapper.ITypeMap
{
private readonly SqlMapper.ITypeMap _defaultTypeMap = new DefaultTypeMap(typeof(T));
public ConstructorInfo FindConstructor(string[] names, Type[] types)
{
return _defaultTypeMap.FindConstructor(names, types);
}
public ConstructorInfo FindExplicitConstructor()
{
return _defaultTypeMap.FindExplicitConstructor();
}
public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
{
return _defaultTypeMap.GetConstructorParameter(constructor, columnName);
}
public SqlMapper.IMemberMap GetMember(string columnName)
{
var member = _defaultTypeMap.GetMember(columnName);
if (member == null)
{
throw new Exception();
}
return member;
}
}
这样做的缺点是,您必须为每个实体配置所有类型映射:
SqlMapper.SetTypeMap(typeof(CustomerRecord), typeof(ThrowWhenNullTypeMap<CustomerRecord>));
然而,这可以使用反射进行配置。
答案 1 :(得分:3)
我是在I solved this same problem for the IEnumerable<dynamic> methods in Dapper之后来到这里的。然后我找到了提案solve the issue for Query<T>;但这似乎无处可去。
我的回答建立在@HenkMollema提出的答案的基础上,并在解决方案中使用他的课程,因此对他有所帮助......
解决IEnumerable&lt; dynamic&gt;方案,我创建了一个“SafeDynamic”类(按照上面的链接看看)。我将静态“Create”方法重构为扩展方法:
public static class EnumerableDynamicExtensions
{
public static IEnumerable<dynamic> Safe(this IEnumerable<dynamic> rows)
{
return rows.Select(x => new SafeDynamic(x));
}
}
然后我创建了一个DapperExtensions类来提供Query和Read的'Safe'版本(在QueryMultiple之后使用Read),给我...
internal static class DapperExtensions
{
public static IEnumerable<dynamic> SafeQuery(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
{
return cnn.Query(sql, param, transaction, buffered, commandTimeout, commandType).Safe();
}
public static IEnumerable<dynamic> SafeRead(this SqlMapper.GridReader gridReader, bool buffered = true)
{
return gridReader.Read(buffered).Safe();
}
}
为了解决这个问题,我添加了一个“SafeQuery&lt; T&gt;” DapperExtensions的方法,负责为您设置类型映射:
private static readonly IDictionary<Type, object> TypesThatHaveMapper = new Dictionary<Type, object>();
public static IEnumerable<T> SafeQuery<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
{
if (TypesThatHaveMapper.ContainsKey(typeof(T)) == false)
{
SqlMapper.SetTypeMap(typeof(T), new ThrowWhenNullTypeMap<T>());
TypesThatHaveMapper.Add(typeof(T), null);
}
return cnn.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType);
}
因此,如果原始海报将对Query的调用更改为SafeQuery,则应该按照他的要求进行操作
编辑25/1/17 改进以避免静态字典上的线程问题:
private static readonly ConcurrentDictionary<Type, object> TypesThatHaveMapper = new ConcurrentDictionary<Type, object>();
public static IEnumerable<T> SafeQuery<T>(this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
{
TypesThatHaveMapper.AddOrUpdate(typeof(T), AddValue, UpdateValue);
return cnn.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType);
}
private static object AddValue(Type type)
{
SqlMapper.SetTypeMap(type, XXX); // Apologies... XXX is left to the reader, as my implementation has moved on significantly.
return null;
}
private static object UpdateValue(Type type, object existingValue)
{
return null;
}
答案 2 :(得分:1)
我想通过提供一个包含他的&#34; SafeQuery&#34;的视觉工作室项目来扩展@Richardissimo的答案。延伸到Dapper,包裹得很好,整洁,经过测试。
https://github.com/LarrySmith-1437/SafeDapper
我现在在我的所有项目中使用它来帮助保持DAL清除错误映射的数据,并感觉需要共享。我本来会发布一个Nuget,但是对Dapper本身的依赖使得发布项目更加容易,消费者可以更新对他们想要的Dapper版本的引用。所有人都身体健康。