Как разобрать 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; }