【问题标题】:Entity Framework can't handle a simple table variable?实体框架无法处理简单的表变量?
【发布时间】:2019-12-19 18:02:10
【问题描述】:
  • 存储过程的最后一行:select * from @t
  • 更新模型并找到存储过程
  • 尝试使用向导导入新函数,但提示找不到列。

真的吗?有人告诉我这是在撒谎。

create procedure WorkIt
as
set nocount on

create table #pivot
(
    Name varchar(30),
    Value decimal,
    Grade varchar(2)
)

insert into #pivot
select 'Repeating Pct', 1, 'K'
union all
select 'Repeating Pct', 2, '1'
union all
select 'Repeating Pct', 3, '2'
union all
select 'Repeating Pct', 4, '3'
union all
select 'Repeating Pct', 5, '4'
union all
select 'Repeating Pct', 6, '5'
union all
select 'Repeating Pct', 7, '6'  
union all
select 'Repeating Pct', 8, '7'
union all
select 'Repeating Pct', 9, '8'
union all
select 'Repeating Pct', 10, '9'
union all
select 'Repeating Pct', 11, '10'
union all
select 'Repeating Pct', 12, '11'
union all
select 'Repeating Pct', 13, '12'
declare @t table
(
    name varchar(30),
    K decimal (15,5) ,
    [1] decimal (15,5),
    [10] decimal (15,5),
    [11] decimal (15,5),
    [12] decimal (15,5),
    [2] decimal (15,5),
    [3] decimal (15,5),
    [4] decimal (15,5),
    [5] decimal (15,5),
    [6] decimal (15,5),
    [7] decimal (15,5),
    [8] decimal (15,5),
    [9] decimal (15,5)
)
insert into @t
exec dbo.CrossTabWithoutSumWithOrderBy #pivot, 'Name', null, 'Grade', 'Value', 
    -- sort repeating pct to bottom
    'case name when ''Repeating Pct'' then 999 else 0 end'

drop table #pivot
select * from @t

结果

name    K   1   10  11  12  2   3   4   5   6   7   8   9
Repeating Pct   2.00000 11.00000    12.00000    13.00000    3.00000 4.00000 5.00000 6.00000 7.00000 8.00000 9.00000 10.00000    1.00000

【问题讨论】:

  • 也许使用表值函数而不是存储过程
  • 不。我想使用存储过程,而不是 UDF。
  • @Joe:EF 根本不支持表值函数。

标签: c# entity-framework-4


【解决方案1】:

当实体框架尝试从存储过程中检索列时,它会调用SET FMTONLY ON,然后执行存储过程。当FMTONLYON 时,执行只返回元数据,并且它不适用于存储过程中的一些高级构造 - 例如动态 SQL、临时表以及表变量。

你有三个选择:

  • another answer 中所述,在存储过程的开头添加SET FMTONLY OFF。这将导致您的存储过程真正执行,因此请确保它只读取数据 - 每次尝试检索列时都会执行任何插入、更新或删除!
  • 手动定义复杂类型
  • 修改您的存储过程以不使用任何这些功能

【讨论】:

  • 感谢您的解决方案。尝试了你的第一颗子弹,但没有奏效。手动定义一个复杂的类型现在是一件很耗时的事情,而且是未来维护的噩梦。第三个是不可接受的。我想你想告诉我的是,Entity Framework 只能处理 SQL Server 支持的一些最基本的功能。对吗?
  • 这不是 EF 的问题。 EF 必须调用SET FMTONLY ON 以确保存储过程不会意外触发任何数据修改,并且一旦调用,SQL 服务器的行为就会有所不同——这就是 SQL 服务器的“功能”。
  • 感谢您的耐心等待并确认我担心的事情可能是真的。我希望在未来版本的 EF 中支持基本和广泛使用的东西,如临时表和/或表变量。现在我将避免使用 EF,除了最简单的存储过程。
  • @O.O 这显然是一个老问题,但我还是想在这里记录一下。 SET FMTONLY OFF 不起作用的原因可能是因为您拨打电话的位置。将调用放在 SP 主体的 BEGIN 中,而不是使用 SSMS 在执行“修改”时默认添加的 SET QUOTED_IDENTIFIER ON 等调用,因为这些调用实际上并不是 SP 的一部分。
  • 这个答案与下面的答案相结合对我有用。谢谢。
【解决方案2】:

我在 edmx 上遇到了类似的问题(在我的情况下是 if else 语句),有一个解决方法。在更新 edmx 之前,声明一些返回类型的变量,选择它们。更新模型,然后使用您的真实代码修改您的存储过程。 即:

declare @name varchar(30),
    @K decimal (15,5) ,
    @x1 decimal (15,5),
    @x10 decimal (15,5),
    @x11 decimal (15,5),
    @x12 decimal (15,5),
   @x2 decimal (15,5),
    @x3 decimal (15,5),
    @x4 decimal (15,5),
    @x5 decimal (15,5),
   @x6 decimal (15,5),
    @x7 decimal (15,5),
    @x8 decimal (15,5),
    @x9 decimal (15,5)

Select @name, @k, @x1, @x10, @x11, @x12, @x2, @x3, @x4, @x5, @x6, @x7, @x8, @x9

当然,你应该在你的存储过程中保留这个虚拟代码的注释,并在其中写一个注释。这样当任何人使用 edmx 更新它时,都应该取消注释这个虚拟代码并注释真实代码。

【讨论】:

  • 这个答案与上面的答案相结合对我有用。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多