Дополнительный столбец EF Core обрабатывается по мере необходимости

Мне нужно прочитать результат хранимой процедуры, вызванной из EF Core, которая включает элементы, предназначенные для целей форматирования электронных таблиц, например строки только с нулевыми значениями. Мой код в основном работает, но есть два столбца, которые приводят к сбою запроса, когда я их включаю.

Вот мой класс модели (для краткости включены только несколько реквизитов):

public class StoredProcRecord
{
    [Column("Prod Line")]
    public string ProductLine { get; set; }

    [Column("Current Sales")]
    public decimal? CurrentSales { get; set; }

    [Column("Current Margin $")]
    public decimal? CurrentMargin { get; set; }
}

Вот фрагмент части вывода, если я запускаю хранимую процедуру из SQL Server Management Studio:

Сохраненный вывод процедуры

Вот как я зарегистрировал тип как модель объекта с помощью EF Core в контексте БД:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Query<StoredProcRecord>();
}

Вот как я вызываю хранимую процедуру:

return _context.Query<StoredProcRecord>().FromSql("EXECUTE my_stored_proc").ToList();

В этом примере EF Core всегда выдает исключение при попытке вызвать FromSql() с сообщением:

Требуемый столбец «Текущая маржа $» отсутствовал в результатах операции «FromSql».

Согласно документам EF Core, если столбец может принимать значения NULL, тогда он не требуется. Тем не менее, я получаю это исключение, в котором утверждается, что требуется «Текущая маржа $». Это также происходит только со свойством CurrentMargin, а не со свойством CurrentSales, которое использует тот же тип. Если я удалю CurrentMargin, все будет работать нормально, и я просто упущу это свойство.

Я попытался использовать [Column(Order = 2)] вместо именованного столбца, думая, что, возможно, знак доллара в имени столбца как-то связан с этим, но это приводит к:

Требуемый столбец «CurrentMargin» отсутствовал в результатах операции «FromSql».

Включение как порядка, так и имени приводит к ошибке того же типа.

Стоит отметить, что это не хранимая процедура, которую я могу обновлять.

Чем свойство CurrentMargin отличается от свойства CurrentSales, что приводит к такому сбою? Есть ли какой-то особый способ обработки знака доллара в имени столбца? Я что-то совсем другое упускаю?

Изменить:

Вот фрагмент из самого конца хранимой процедуры, где выводится результирующая таблица. Я включаю это, чтобы показать, что «Current Margin $» действительно является одним из имен столбцов. На самом деле я скопировал/вставил прямо из хранимой процедуры, чтобы убедиться, что я не ошибся при вводе имени столбца.

BEGIN
-- bulk of stored procedure that builds #tmp_tbl omitted for length
SELECT 
'Prod Line'          = pl_key,
'Current Sales'      = curr_sales,
'Current Margin $'   = curr_margin
FROM #tmp_tbl
END

person HotN    schedule 15.03.2019    source источник
comment
Yet, I receive that exception that claims "Current Margin $" is required. -Нет, это не так! На самом деле это говорит о том, что в выводе, возвращаемом запросом, нет такого столбца с именем Current Margin $.   -  person TanvirArjel    schedule 16.03.2019
comment
Похоже, имя столбца, возвращаемое SP, не является «Current Margin $». Проверьте наличие пробелов или других символов после $.   -  person Ivan Stoev    schedule 16.03.2019
comment
@TanvirArjel Я обновил свой вопрос, включив в него последнюю часть хранимой процедуры, чтобы показать фактический результат. Это должно более четко показать, что Current Margin $ — это фактическое имя генерируемого столбца, которое соответствует приведенному выше снимку экрана.   -  person HotN    schedule 16.03.2019
comment
Проблема в том, что я попробовал код из поста, и он работает с тестовым SP, как этот CREATE PROCEDURE [dbo].[my_stored_proc] AS DECLARE @DATA TABLE(ProductLine VARCHAR(20), CurrentSales decimal, CurrentMargin decimal); insert into @DATA values('1', 1, 1); insert into @DATA values('2', 2, 2); insert into @DATA values('3', 3, 3); insert into @DATA values('4', 4, 4); insert into @DATA values(null, null, null); select T.ProductLine [Prod Line], T.CurrentSales [Current Sales], T.CurrentMargin [Current Margin $] from @DATA T; RETURN 0 Другими словами, он не воспроизводит   -  person Ivan Stoev    schedule 17.03.2019
comment
@IvanStoev Хм ... ваш образец действительно работает, как я и ожидал. К сожалению, это только делает первоначальную проблему еще более загадочной, потому что ошибка исходной SP специально вызывает Текущую маржу $ в качестве проблемного поля, но я не могу заставить вашу SP выйти из строя каким-либо подобным образом, как бы я ни пытался изменить его.   -  person HotN    schedule 17.03.2019
comment
Знаете что, SELECT вашего SP выглядит странно, возможно, все возвращаемые имена столбцов не соответствуют вашим ожиданиям — EF Core просто сообщает имя первого отсутствующего столбца в алфавитном порядке. Чтобы увидеть, что вы получите, выполните следующий фрагмент var cn = _context.Database.GetDbConnection(); var cmd = cn.CreateCommand(); cmd.CommandText = "my_stored_proc"; cn.Open(); var dr = cmd.ExecuteReader(); var cols = Enumerable.Range(0, dr.FieldCount).Select(i => dr.GetName(i)).ToList(); и проверьте переменную cols в отладчике.   -  person Ivan Stoev    schedule 17.03.2019
comment
@IvanStoev Большое спасибо за помощь! См. мой опубликованный ответ о том, в чем на самом деле была проблема, но знайте, что я не думаю, что понял бы это без ваших предложений по устранению неполадок. Ваш последний комментарий заставил меня снова все проверить, так как результаты этих звонков выглядели именно так, как я ожидал, когда я обнаружил свою ошибку. Спасибо, что остаетесь со мной, хотелось бы, чтобы я мог дать вам больше голосов!   -  person HotN    schedule 19.03.2019


Ответы (1)


Смущающий ответ на этот вопрос: убедитесь, что вы внимательно читаете свой код, особенно такие вещи, как строковые значения.

В этом случае у меня есть две хранимые процедуры, которые в конечном итоге будут использоваться моим приложением, bv_xls_profit_sum_v2 и bv_xls_prod_sum_v2. Я реализовал использование результатов первой хранимой процедуры, но случайно предоставил EF имя второй хранимой процедуры. Столбцы из этих двух не совпадают, поэтому ошибка, которую я получал об отсутствующем обязательном столбце, была не о том, был ли столбец обнуляемым, а на самом деле был случай, когда столбец действительно полностью отсутствовал в наборе результатов. Это было не очевидно при тестировании с помощью SQL Server Management Studio, потому что я не осознавал, что выполняю другую хранимую процедуру.

Бонус "Ответ":

Прежде чем понять свою глупую ошибку, я нашел обходной путь, который я оставлю здесь на случай, если он окажется кому-то полезным. Мое приложение имеет свой собственный экземпляр SQL Server, но также запрашивает другой экземпляр SQL Server, который не контролируется приложением (именно там живут рассматриваемые хранимые процедуры). Чтобы обойти проблему, с которой я боролся, я подключил другой экземпляр SQL Server к своему как связанный сервер. Затем я продублировал хранимую процедуру, которую хотел вызвать, обновил ее, чтобы она запрашивала связанный сервер, удаляла нежелательные пустые строки и возвращала данные, используя имена столбцов, соответствующие моему классу модели. Это работает и позволяет мне управлять хранимой процедурой, хотя, вероятно, увеличивает задержку при получении набора результатов от запроса измененной хранимой процедуры.

person HotN    schedule 19.03.2019