簡體   English   中英

Dapper對列中的NULL值進行異常轉換

[英]Dapper Cast Exception on NULL value in column

我正在使用SQLite及其閉包擴展來存儲層次結構。 非關閉表創建為

_connection.Execute(@"CREATE TABLE IF NOT EXISTS category (
    id INTEGER NOT NULL PRIMARY KEY,
    name TEXT,
    parent_id INTEGER,
    FOREIGN KEY (parent_id) REFERENCES category (id)
);");

插入根節點,並將parent_id設置為NULL Dapper往返的類是

public class TestRecord
{
    public long id;
    public string name;
    public long? parent_id;
}

在我看來,Dapper讀取根節點或非根節點應該沒有任何問題,因為該列已明確標記為可空。 但是,像這樣查詢所有條目:

_connection.Query<TestRecord>(@"SELECT * FROM category;");

將拋出根節點,因為它不能強制轉換某些內容(這很奇怪,因為任何地方都沒有涉及32bit的整數):

Unhandled Exception: System.Data.DataException: 
Error parsing column 2 (parent_id=1 - Int64) ---> 
System.InvalidCastException: Unable to cast object of type 'System.Int64' to type 
  'System.Int32'.

一種返回正確結果的解決方法

.Query<TestRecord>(@"SELECT id, IFNULL(parent_id, 0), name FROM category;");

但這是不可行的,原因有幾個。 我特別不想列出查詢中的所有列,也不想引入parent_id特殊情況。

不使用Dapper並手動進行映射就可以與原始查詢配合使用,當然,sqlite CLI也是如此。

因此,如何使Dapper接受並映射正確的條目?

編輯:我正在使用Dapper 1.50.4和dotnet core 2.0。

根據Marc的評論,這不應該發生,並且會警告庫修復。 該問題正在此處跟蹤並且還會影響其他人。

sqlite可為空類型的解決方案。 鏈接

public class NullableLongHandler : SqlMapper.TypeHandler<long?>
{
    public override void SetValue(IDbDataParameter parameter, long? value)
    {
        if (value.HasValue)
            parameter.Value = value.Value;
        else
            parameter.Value = DBNull.Value;
    }

    public override long? Parse(object value)
    {
        if (value == null || value is DBNull) return null;
        return Convert.ToInt64(value);
    }
}

SqlMapper.AddTypeHandler(new NullableLongHandler());

如果您使用“ INTEGER”創建表,則Sqlite將創建int32,但是您的模型中有一個long,我想這是在考慮無效的強制轉換異常,BigInt必須用於給出一個long。

因此,您應該將請求更改為:

_connection.Execute(@"CREATE TABLE IF NOT EXISTS category (
  id BIGINT NOT NULL PRIMARY KEY,
  name TEXT,
  parent_id BIGINT,
  FOREIGN KEY (parent_id) REFERENCES category (id)
);");

或使用符合您要求的模型:

public class TestRecord
{
    public int id;
    public string name;
    public int? parent_id;
}

我猜您的帶有“ IFNULL(parent_id,0)”的請求正在工作,因為它包含強制轉換,因為0可以視為int32。

在這個課程上嘗試一下,它應該可以工作

public class TestRecord
{
    public Int64 id;
    public string name;
    public Int64? parent_id;
}

更新資料

嘗試

public class TestRecord
{
    public Int32 id;
    public string name;
    public Int32? parent_id;
}

因為這是你的錯誤

System.InvalidCastException: Unable to cast object of type 'System.Int64' to type 
  'System.Int32'.

因為如果此錯誤意味着無法將int32轉換為int64,則此時最好更改基本數據的類型

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM