Я использую EF Core 3.0 для извлечения данных из хранимой процедуры SQL Server в свою объектную модель с именем Recipient
. Модель Recipient
имеет несколько определенных свойств, EnvelopeId
и Name
, которые не возвращаются из хранимой процедуры. Когда я вызываю хранимую процедуру с помощью FromSqlInterpolated
, я получаю сообщение об ошибке
Обязательный столбец EnvelopeId1 отсутствовал в результатах операции FromSql.
Из того, что я прочитал в документации EF Core, я должен иметь возможность добавить атрибут [NotMapped]
к этим свойствам, и EF Core должен иметь возможность игнорировать их при чтении или записи в базу данных, верно? К сожалению, у меня это не работает, и я получаю указанную выше ошибку.
Если я добавлю два столбца в хранимую процедуру и удалю атрибут [NotMapped]
в своей объектной модели, все будет работать нормально. Это доказывает, что другие мои имена столбцов / свойств совпадают правильно и нигде нет опечаток.
Я видел предложения использовать DbQuery
вместо DbSet
, но он устарел, поэтому я не хочу его использовать. Я видел предложения об использовании двух разных объектных моделей, одна со свойствами, точно соответствующими результирующему набору хранимой процедуры, но это просто приводит к множеству дополнительных моделей. Что я здесь делаю не так?
Моя объектная модель:
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MyNamespace.Models
{
public class Recipient
{
[Key]
public long RecipientId { get; set; }
[NotMapped]
public Guid? EnvelopeId { get; set; }
public string Type { get; set; }
public string UserId { get; set; }
public string Email { get; set; }
[NotMapped]
public string Name { get; set; }
public string RoleName { get; set; }
public int RoutingOrder { get; set; }
public string Status { get; set; }
public DateTime StatusDate { get; set; }
public Recipient() { }
}
}
Мой контекст БД:
using Microsoft.EntityFrameworkCore;
using MyNamespace.Models;
namespace MyNamespace.Data
{
public class MyDbContext : DbContext
{
public virtual DbSet<Recipient> Recipient { get; set; }
public virtual DbSet<Envelope> Envelope { get; set; }
public virtual DbSet<Template> Template { get; set; }
public MyDbContext (DbContextOptions<MyDbContext> options) : base(options)
{ }
}
}
Мой код ошибки:
FormattableString sql = $"EXEC dbo.MyStoredProcedure @Param1={param1}, @Param2={param2}";
var result = await MyDbContext.Recipient.FromSqlInterpolated(sql).ToListAsync();
Изменить №1 ...
Envelope
объектная модель:
public class Envelope
{
[Key]
public Guid EnvelopeId { get; set; }
public string Status { get; set; }
public DateTime StatusDate { get; set; }
public DateTime StatusPollDate { get; set; }
[NotMapped]
public List<Recipient> Recipients { get; set; }
public Envelope() {
Recipients = new List<Recipient>();
StatusPollDate = DateTime.Parse("1753-01-01");
}
}
Схема набора результатов хранимой процедуры:
[RecipientId] bigint,
[Type] varchar(20),
[UserId] varchar(50),
[Email] varchar(100),
[RoleName] varchar(100),
[RoutingOrder] int,
[Status] varchar(13),
[StatusDate] datetime
Прочитав некоторые ответы и комментарии, я понял, что свойство shadow создается EF, поскольку он распознает, что Recipient
является дочерним по отношению к объекту Envelope
. Честно говоря, мне действительно следует включить EnvelopeId
в набор результатов (и удалить [NotMapped]
), чтобы успокоить EF Core. Единственная причина, по которой я не возвращал EnvelopeId
в результирующем наборе хранимой процедуры, заключалась в том, что я передал его в качестве входного параметра для начала и подумал, что он тратит сетевые ресурсы, чтобы передать что-то, а затем вернуть это в каждом результат установлен рекорд.
Теперь я не знаю, откуда взялся EnvelopeId1
, но именно об этом упоминается в сообщении об ошибке. Как вы можете видеть в моих объектных моделях и схеме набора результатов хранимых процедур, у меня всегда есть ссылки только на EnvelopeId
. Я предполагаю, что, когда EF Core решил создать свойство shadow, он не смог использовать EnvelopeId
, поскольку он уже был у меня в моей объектной модели, поэтому он создал свойство с именем EnvelopeId1
, а затем ожидал, что он будет присутствовать в наборе результатов хранимая процедура.
EnvelopeId1
определено где-либо в моем коде или в наборе результатов хранимой процедуры, ноEnvelopeId1
- это то, что показывает сообщение об ошибке. - person ConfuedProblemSolver   schedule 05.11.2019EnvelopeId
концептуально является первичным ключом для другого объекта (Envelope
), но в соответствии с тем, как я определил свою объектную модельRecipient
, я называю его толькоGuid?
, поэтому он не потребуется. Но ваш комментарий заставляет меня думать, что он может иметь какое-то отношение к типу данныхGuid?
. Я пробовал нечто подобное с типом данныхlong
, и атрибут[NotMapped]
работал точно так, как ожидалось. - person ConfuedProblemSolver   schedule 05.11.2019Envelope
, а также образец вывода SP. То, что вы считаете, что свойство не требуется, не означает, что оно не требуется. :) - person Chris Schaller   schedule 05.11.2019Recipients
вEnvelope
помечено как не сопоставлено? Вы не хотите, чтобы ограничение ForeignKey в базе данных? Похоже, вы могли создать схему базы данных до того, как пометилиRecipients
как не сопоставлен и с тех пор не меняли схему базы данных. - person Chris Schaller   schedule 07.11.2019