Как разобрать UGID postgresql в строку C# с помощью Dapper FluentMap?

У меня есть функция, которая возвращает (среди прочего) UUID. Я использую FluentMap для обработки некоторых возвращаемых столбцов, которые содержат пробелы, но рассматриваемый столбец (invoice_id) не имеет этой проблемы.

Сокращенная версия запроса базы данных:

CREATE FUNCTION fnSearchInvoices (
    _SearchTerm TEXT
) 
RETURNS TABLE(
    store_id INTEGER,
    customer_id TEXT,
    "Customer Name" TEXT,
    "Store Name" TEXT,
    "Email" TEXT,
    invoice_id UUID
) AS $$
SELECT
I.store_id,
I.customer_id,
C.name AS "Customer Name",
S.name AS "Store Name",
C.email AS "Email",
I.id AS invoice_id
FROM Invoice I
JOIN Customer C
ON I.customer_id = C.id
JOIN Store S
ON I.store_id = S.id
WHERE
{bunch of conditions for matching search term}
;
$$ LANGUAGE SQL;

Класс запроса:

public class SearchRequest
{
    public string SearchTerm { get; set; }
    public int PagingOffSet { get; set; }
    public int PageSize { get; set; }
    public string SortField { get; set; }
    public string SortDirection { get; set; }
}

Класс результата:

public class SearchResult
{
    public int StoreID { get; set; }
    public string CustomerID { get; set; }
    public string CustomerName { get; set; }
    public string StoreName { get; set; }
    public string Email { get; set; }
    public string InvoiceID { get; set; }
    public int TotalRecords { get; set; }
}

EntityMap:

public class SearchResultMap : EntityMap<SearchResult>
{
    public SearchResultMap()
    {
        Map(p => p.CustomerID).ToColumn("Customer Name");
        Map(p => p.StoreName).ToColumn("Store Name");
    }
}

И, наконец, вызов в базу данных из C#:

IDbConnection dbConnection = new NpgsqlConnection(strDbConnectionString)

string strCommand = "SELECT *, count(*) OVER() AS total_records ";
strCommand += "FROM fnSearchInvoices(:SearchTerm) ";
strCommand += "ORDER BY \"" + cSearchRequest.SortField + "\" " + cSearchRequest.SortDirection + " ";
strCommand += "LIMIT :PageSize OFFSET :PagingOffSet;";

cSearchResponseList = dbConnection.Query<T>(strCommand, cSearchRequest).ToList();

Когда я запускаю приведенный выше код с обработкой исключений, я получаю следующую ошибку (это сообщение об исключении плюс внутреннее сообщение):

Error: Error parsing column 6 (invoice_id=12345678-abcd-1234-abcd-1234567890ef - Object) Details: System.InvalidCastException: Object must implement IConvertible. at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) at Deserializeabcdef12-abcd-1234-abcd-abcdef123456(IDataReader )

Я могу удалить InvoiceID от SearchResponse класс и запрос отлично работает; этот столбец игнорируется, а все остальное отображается, как и ожидалось.

Функция db используется в другом месте, и я бы не стал ее менять, хотя в качестве последнего средства я мог бы использовать эту функцию. Это просто потребовало бы дополнительных изменений в другом месте, которые выходят за рамки того, над чем я работаю. И я понимаю, что должен быть в состоянии изменить SELECT в моем C# явно приводить UUID к TEXT вне вызова функции, получая все столбцы по имени, а не с *, что я собираюсь попробовать позже. Но для дальнейшего использования, есть ли способ заставить Dapper правильно отобразить UUID-возвращение из запроса в строку C#?

1 ответ

К сожалению, Dapper попытается связать тип через то, что база данных специально имеет для типа. Ваш столбец накладной обозначается как строковый тип.

Если у вас есть столбец возврата запроса:

CAST([Invoice] AS NVARCHAR(MAX)) AS [Invoice]

Dapper теперь может корректно отображать ваш объект, который вы обозначили как строку. Это должно исправить вашу проблему. Лучше всего, если база данных правильно приведёт колонку для вас в NVARCHAR(MAX),

В противном случае вам нужно будет изменить свойство объекта.

public Guid Invoice { get; set; }
Другие вопросы по тегам