Entity Framework Core 2.0 执行不 return PK 的存储过程
Entity Framework Core 2.0 execute stored procedure that doesn't return a PK
EF Core 2.0 似乎要求执行存储过程的结果具有主键。有没有解决的办法?并非所有存储过程 return 都是唯一可识别的行。谢谢!
不,目前 EF Core 无法做到这一点,但在 roadmap 的未来版本中,虽然可能不适用于 v2.1。在 GitHub 上查看这些问题:
我在做开发的时候也发现了这个。您总是可以直接使用 Row_Number() Over() as [ObjectName]Id 这样简单的东西在 SQL 服务器中虚拟一个自增键 return。这是一个廉价的 hack,但它满足了需要,因为您可以在这个字段上设置 [Key] 装饰,得到 return,并且它将在其他不明显的 return 中是不同的。
declare @Temp table ( val char);
insert into @Temp values ('a'),('b'),('c');
select
--this column is arbitrarily made and only exists to satisfy uniqueness.
--it provides NO functionality to the underlying code being returned.
ROW_NUMBER() Over(order by val) as TempId
, val
from @Temp
以及 return 的模型:
public sealed class pTempResult
{
[Key]
public int TempId{ get; set; }
public int Val { get; set; }
}
对于我所做的,我还在我创建的上下文中启用了一个 DbSet 对象:
public virtual DbSet<pTempResult> { get; set; }
然后在我的控制器中我会这样调用它:
await _context.pTempResult.FromSql("pMyProc @p0, @p1, @p2", parameters: new[] { 1, "string" }).ToListAsync();
这样我得到了一个结构良好的对象,但同时直接调用了我需要得到这个结构良好的对象的过程。请记住,在 Entity Framework Core AFAIK 中,您必须添加迁移以创建 proc(如果它尚不存在)。 EG:如果我想从代码中填充数据库中的过程,我需要在迁移的 'up' 部分中手动编写 SQL:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(
"create proc pGetTemp" +
"( @Id int, @Text varchar(16) as " +
"BEGIN " +
"Select * from Temp " +
"Where Id = @Id and text = @Text " +
"END "
);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("drop proc pGetTemp");
}
同样,这不是很好,也不是最优的,但是如果你想使用带有 Entity Framework Core 的程序,我可以验证它是否有效。
EF Core 2.0 似乎要求执行存储过程的结果具有主键。有没有解决的办法?并非所有存储过程 return 都是唯一可识别的行。谢谢!
不,目前 EF Core 无法做到这一点,但在 roadmap 的未来版本中,虽然可能不适用于 v2.1。在 GitHub 上查看这些问题:
我在做开发的时候也发现了这个。您总是可以直接使用 Row_Number() Over() as [ObjectName]Id 这样简单的东西在 SQL 服务器中虚拟一个自增键 return。这是一个廉价的 hack,但它满足了需要,因为您可以在这个字段上设置 [Key] 装饰,得到 return,并且它将在其他不明显的 return 中是不同的。
declare @Temp table ( val char);
insert into @Temp values ('a'),('b'),('c');
select
--this column is arbitrarily made and only exists to satisfy uniqueness.
--it provides NO functionality to the underlying code being returned.
ROW_NUMBER() Over(order by val) as TempId
, val
from @Temp
以及 return 的模型:
public sealed class pTempResult
{
[Key]
public int TempId{ get; set; }
public int Val { get; set; }
}
对于我所做的,我还在我创建的上下文中启用了一个 DbSet 对象:
public virtual DbSet<pTempResult> { get; set; }
然后在我的控制器中我会这样调用它:
await _context.pTempResult.FromSql("pMyProc @p0, @p1, @p2", parameters: new[] { 1, "string" }).ToListAsync();
这样我得到了一个结构良好的对象,但同时直接调用了我需要得到这个结构良好的对象的过程。请记住,在 Entity Framework Core AFAIK 中,您必须添加迁移以创建 proc(如果它尚不存在)。 EG:如果我想从代码中填充数据库中的过程,我需要在迁移的 'up' 部分中手动编写 SQL:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(
"create proc pGetTemp" +
"( @Id int, @Text varchar(16) as " +
"BEGIN " +
"Select * from Temp " +
"Where Id = @Id and text = @Text " +
"END "
);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("drop proc pGetTemp");
}
同样,这不是很好,也不是最优的,但是如果你想使用带有 Entity Framework Core 的程序,我可以验证它是否有效。