【发布时间】:2019-11-04 21:35:40
【问题描述】:
我正在使用 EF Core 3.0 将数据从 SQL Server 存储过程提取到名为 Recipient 的对象模型中。 Recipient 模型定义了两个属性,EnvelopeId 和 Name,它们不是从存储过程返回的。当我使用FromSqlInterpolated 调用存储过程时,我收到错误消息
“FromSql”操作的结果中不存在所需的列“EnvelopeId1”
根据我在 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
在阅读了一些答案和 cmets 后,我意识到 EF 正在创建一个影子属性,因为它识别出 Recipient 是 Envelope 对象的子对象。老实说,我真的应该在结果集中包含EnvelopeId(并删除[NotMapped])以安抚EF Core。我没有在存储过程的结果集中返回EnvelopeId 的唯一原因是因为我一开始就将它作为输入参数传入,并认为传入某些内容然后取回它是在浪费网络资源在每个结果集记录中。
现在我不知道EnvelopeId1 来自哪里,但这就是错误消息中提到的内容。正如您在我的对象模型和存储过程结果集架构中看到的那样,我只引用了EnvelopeId。我最好的猜测是,当 EF Core 决定创建一个影子属性时,它不能使用 EnvelopeId,因为我已经在我的对象模型中拥有它,所以它创建了一个名为 EnvelopeId1 的对象,然后期望它出现在存储过程的结果集。
【问题讨论】:
-
EnvelopeId1与EnvelopeId? -
EnvelopeId 听起来像一个 pirmary 键,所以你会遇到一些问题使它成为可选的。除此之外,您还得到了 tymtam 指出的命名不匹配。
-
@tymtam,这不是错字。我的代码或存储过程结果集中的任何地方都没有定义
EnvelopeId1,但错误消息显示的是EnvelopeId1。 -
@Christopher,是的
EnvelopeId在概念上是不同对象 (Envelope) 的主键,但我定义Recipient对象模型的方式,我只将其称为Guid?所以不需要。但是你的评论让我觉得这可能与Guid?的数据类型有关。我用long的数据类型尝试了类似的操作,[NotMapped]属性完全按预期工作。 -
您需要发布
Envelope的架构以及 SP 输出示例。仅仅因为您认为不需要属性,并不意味着它不是必需的。 :)
标签: c# sql-server .net-core-3.0 ef-core-3.0