如何从 Dapper 查询返回 null 而不是 default(T)?

Posted

技术标签:

【中文标题】如何从 Dapper 查询返回 null 而不是 default(T)?【英文标题】:How to return null from a Dapper query rather than default(T)? 【发布时间】:2012-07-30 11:29:24 【问题描述】:

我正在使用Dapper 通过存储过程进行一些只读数据库调用。我有一个查询,要么返回 1 行,要么什么都不返回。

我正在像这样使用 Dapper:

using (var conn = new SqlConnection(ConnectionString))

    conn.Open();

    return conn.Query<CaseOfficer>("API.GetCaseOfficer", 
        new  Reference = reference , 
        commandType: CommandType.StoredProcedure).FirstOrDefault();

返回的 CaseOfficer 对象如下所示:

public class CaseOfficer

    public string Title  get; set; 
    public string FirstName  get; set; 
    public string LastName  get; set; 
    public string Email  get; set; 
    public string Telephone  get; set; 

然后通过 ASP.NET Web API 应用程序将其作为 JSON 返回。

当存储过程返回结果时,我得到以下信息:


    title: "Mr",
    firstName: "Case",
    lastName: "Officer",
    email: "test@example.com",
    telephone: "01234 567890"

但是当它什么也没返回时,我得到:


    title: null,
    firstName: null,
    lastName: null,
    email: null,
    telephone: null

我怎样才能让 Dapper 返回 null(以便我可以检查并返回 404),而不是默认值(CaseOfficer)?

【问题讨论】:

仅供参考,默认(CaseOfficer)为空。看起来它正在创建对象而不是填充字段。不能再帮你了,因为我不认识 Dapper 【参考方案1】:

如果你的 SP 没有返回一行,那么 dapper 就不会返回一行;所以首先要检查:你的 SP 是否可能返回一个空行?一行所有nulls ?还是返回 0 行?

现在,假设没有返回任何行,如果 CaseOfficerclassFirstOrDefault(标准 LINQ-to-Objects 事物)将返回 null,或者如果 CaseOfficer 是 @,则返回默认实例987654327@。所以接下来:检查CaseOfficerclass(我想不出任何理智的理由是struct)。

但是:带有FirstOrDefault 的小巧玲珑通常已经做了你想要的。

【讨论】:

SP 从外观上返回一行nulls。 CaseOfficer 是一个类。看看我是否可以修改存储过程以返回 0 行。 @James 另一种选择是找到一个必须具有值的列,并对其进行测试,例如.FirstOrDefault(x =&gt; x.FirstName != null) 当 T 是可空类型(例如int?)时,Dapper 是否也返回 null? @MarcGravell,如果我们使用 Query 执行存储过程并且如果存储过程不返回任何行,则 Dapper 返回计数为 0 的 IEnumerable。如果没有返回行,我们如何获得 null存储过程?我不想用 0 条记录初始化我的列表。在这种情况下,我想将其设置为 null。 @Priya 在我看来,dapper 正在 正确 那里得到它......一个空网格不是空的 - 它只有零行;但是:如果这不是您想要的,只需检查它是否为零行,如果是:在您自己的代码中将其替换为null。在这种情况下,Dapper 没有相应的 API。如果这是单行方案,您可以使用 FirstOrDefault&lt;T&gt; / SingleOrDefault&lt;T&gt;,如果没有返回任何行,则对于任何引用类型 T 将返回 null【参考方案2】:

您可以设置默认属性。

例如:

public class BaseEntity

    public BaseEntity()
    
        if (GetType().IsSubclassOf(typeof(BaseEntity)))
        
            var properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (var property in properties)
            
                // Get only string properties
                if (property.PropertyType != typeof (string))
                
                    continue;
                

                if (!property.CanWrite || !property.CanRead)
                
                    continue;
                

                if (property.GetGetMethod(false) == null)
                
                    continue;
                
                if (property.GetSetMethod(false) == null)
                
                    continue;
                

                if (string.IsNullOrEmpty((string) property.GetValue(this, null)))
                
                    property.SetValue(this, string.Empty, null);
                
            
        
    


public class CaseOfficer : BaseEntity

    public string Title  get; set; 
    public string FirstName  get; set; 
    public string LastName  get; set; 
    public string Email  get; set; 
    public string Telephone  get; set; 

现在,CaseOfficer 获得了自动属性

【讨论】:

以上是关于如何从 Dapper 查询返回 null 而不是 default(T)?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我从 Dapper 返回的对象具有 null 和默认属性值?

使用 Dapper ORM 检查记录是不是存在

Dapper 多参数存储过程查询不会从数据库返回任何内容

从 dapper 中的多个查询返回可枚举的结果

如何从graphql突变返回新记录而不是null

你可以使用 Dapper 来刷新现有的对象引用而不是总是返回新的吗?