2015-08-27 18 views
2

我也有类似的问题,因为在(附加)EF不能从存储过程选择来自#temp表

EF can't infer return schema from Stored Procedure selecting from a #temp table

描述推断回归模式,我已经基于创建的我的存储过程的解决方案解决方案如上所述,但我仍然得到类似的EF错误,我真的不知道为什么或了解我如何解决它。

A member of the type, 'rowNum', does not have a corresponding column in the data reader with the same name.

我的具体错误:

The data reader is incompatible with the specified 'TestModel.sp_SoInfoDocs_Result'. A member of the type, 'rowNum', does not have a corresponding column in the data reader with the same name.

我的存储过程:

ALTER PROCEDURE [dbo].[sp_SoInfoDocs] 
    @searchText nvarchar(200), 
    @PageNumber int, 
    @PageSize int 
AS 
BEGIN 
    IF 1 = 2 
    BEGIN  
     SELECT 
      cast(null as int) as rowNum 
      ,cast(null as text) as serverName 
      ,cast(null as text) as jobName 
      ,cast(null as DATETIME) as oDate 
      ,cast(null as int) as runCount 
      ,cast(null as nvarchar(10)) as orderID 
      ,cast(null as text) as applicationName 
      ,cast(null as text) as memberName 
      ,cast(null as text) as nodeID 
      ,cast(null as nvarchar(10)) as endStatus 
      ,cast(null as int) as returnCode 
      ,cast(null as DATETIME) as startTime 
      ,cast(null as DATETIME) as endTime 
      ,cast(null as nvarchar(50)) as status 
      ,cast(null as text) as owner 
      ,cast(null as bit) as existsNote 
     WHERE 
      1 = 2 
    END 

DECLARE @LowerLimit int; 
SET @LowerLimit = (@PageNumber - 1) * @PageSize; 
DECLARE @UpperLimit int; 
SET @UpperLimit = @PageNumber * @PageSize; 

PRINT CAST (@LowerLimit as varchar) 
PRINT CAST (@UpperLimit as varchar) 

SELECT ROW_NUMBER() over (order by Expr1) as rowNum, * 
into #temp 
from ( 

SELECT  dbo.SOInfo.jobName, dbo.SOInfo.nodeID, dbo.SOInfo.nodeGroup, dbo.SOInfo.endStatus, dbo.SOInfo.returnCode, dbo.SOInfo.startTime, dbo.SOInfo.endTime, 
         dbo.SOInfo.oDate, dbo.SOInfo.orderID, dbo.SOInfo.status, dbo.SOInfo.runCount, dbo.SOInfo.owner, dbo.SOInfo.cyclic, dbo.SOInfo.soInfoID, dbo.SOInfo.docInfoID, 
         dbo.SOInfo.existsNote, dbo.SOInfo.noSysout, dbo.serverInfo.serverName, dbo.Groups.label AS applicationName, Groups_1.label AS memberName, 
         Groups_2.label AS groupName, Groups_3.label AS scheduleTableName, dbo.SOInfo.serverInfoID, dbo.SOInfo.applicationID, dbo.SOInfo.groupID, 
         dbo.SOInfo.memberID, dbo.SOInfo.scheduleTableID, dbo.docFile.docFileID, dbo.docInfo.docInfoID AS Expr1, dbo.docFile.docFileObject 
FROM   dbo.SOInfo INNER JOIN 
         dbo.serverInfo ON dbo.SOInfo.serverInfoID = dbo.serverInfo.serverInfoID INNER JOIN 
         dbo.docInfo ON dbo.SOInfo.docInfoID = dbo.docInfo.docInfoID INNER JOIN 
         dbo.docFile ON dbo.docInfo.docFileID = dbo.docFile.docFileID LEFT OUTER JOIN 
         dbo.Groups AS Groups_3 ON dbo.SOInfo.scheduleTableID = Groups_3.ID LEFT OUTER JOIN 
         dbo.Groups AS Groups_1 ON dbo.SOInfo.memberID = Groups_1.ID LEFT OUTER JOIN 
         dbo.Groups AS Groups_2 ON dbo.SOInfo.groupID = Groups_2.ID LEFT OUTER JOIN 
         dbo.Groups ON dbo.SOInfo.applicationID = dbo.Groups.ID 

         WHERE CONTAINS (docfileObject,@searchText) 
) tbl 

    SELECT Count(1) FROM #temp 

    SELECT rowNum, serverName, jobName ,oDate,runCount,orderID,applicationName,memberName,nodeID, endStatus, returnCode,startTime,endTime,status,owner,existsNote  
    FROM #temp WHERE rowNum > @LowerLimit AND rowNum <= @UpperLimit 
END 

我的总体目标是:

  1. 搜索通过聚集索引表(文档信息)和找到所有行c ontain一个特定的搜索字符串值

  2. 在从其它表与每个DOCINFO对象相关联的同时捕获的元数据

  3. 的动作(1)和实验结果(2)上述被写入到一个#temp表到然后我添加一个rowNum列以使我能够引入分页,例如

  4. 根据提供的PageNumber和PageSize变量,在任何时候都可以返回元数据结果的数量。

什么工作

  1. 我能够成功地创建存储过程。

  2. 在SSMS我能够成功执行存储过程,并提供我所期望的结果,这里是一个例子

    enter image description here

  3. 在EF我已经能够更新并导入存储过程从数据库更新

    enter image description here

  4. 在EF我再能看到功能IMPOR TS和能看到我就能够看到生成的复杂类型

    enter image description here

  5. 我用下面的代码来调用映射

    enter image description here

    enter image description here

  6. 在ED过程

    using (TestEntities context = new TestEntities()) 
    { 
        List<sp_SoInfoDocs_Result> lst = context.sp_SoInfoDocs(searchText, 1, 10).ToList(); 
    } 
    
  7. 我编译和运行我的解决方案,并从EF收到以下错误

    'System.Data.Entity.Core.EntityCommandExecutionException' occurred in EntityFramework.SqlServer.dll

    Additional information: The data reader is incompatible with the specified 'SysviewModel.sp_SoInfoDocs_Result'. A member of the type, 'rowNum', does not have a corresponding column in the data reader with the same name.

我非常新手/基本用户,当谈到这两个SSMS/SQL和EF,这已经捉襟见肘我尽我所知/可以去,我真的不知道要转向下一步以解决这个问题。

我已经通过搜索广泛搜索,可以看到其他谁有类似的问题,并尝试了解决方案建议,但似乎没有为我工作。

我真的会非常非常感谢的人谁可以帮助我了解

  1. 它是什么,是错的/我做了什么错?

  2. 有没有更好的方法来实现我所需要的?

  3. 关于如何解决这个问题的想法。

在此先感谢

+0

也许你需要阅读这一点:在描述一些条件http://stackoverflow.com/a/32128830/5070879简答在那里你不能获取创建映射/提供者/等等所需的元数据... – lad2025

+0

@ lad2025〜感谢您的支持。 –

回答

1

我已经找到了解决办法是使用临时表,然后让我通过我的最终SQL SELECT语句暴露表列代替使用SQL临时变量,然后使用它们作为使用“添加功能导入”功能的EF中的元数据。

下面是我成功工作的示例。

USE [TestDB] 
GO 
/****** Object: StoredProcedure [dbo].[sp_SoInfoDocs_Archive] Script Date: 09/07/2015 10:35:43 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[sp_SoInfoDocs_Archive] 
    @searchText nvarchar(200), 
    @PageNumber int, 
    @PageSize int, 
    @out int = 0 output 

AS 
BEGIN 

DECLARE @LowerLimit int; 
SET @LowerLimit = (@PageNumber - 1) * @PageSize; 
DECLARE @UpperLimit int; 
SET @UpperLimit = @PageNumber * @PageSize; 

-- Create temporary column variables 

Declare @temp TABLE 
(
rowNum INT, 
jobName text, 
nodeID nvarchar(50), 
nodeGroup text, 
endStatus nvarchar(10), 
returnCode int, 
startTime datetime, 
endTime datetime, 
oDate smalldatetime, 
orderID nvarchar(10), 
status nvarchar(50), 
runCount int, 
owner text, 
cyclic text, 
soInfoID int, 
docInfoID int, 
existsNote bit, 
noSysout bit, 
serverName varchar(256), 
applicationName nvarchar(255), 
memberName nvarchar(255), 
groupName nvarchar(255), 
scheduleTableName nvarchar(255), 
serverInfoID int, 
applicationID int, 
groupID int, 
memberID int, 
scheduleTableID int, 
docFileID int, 
Expr1 int, 
docFileObject varbinary(MAX) 
) 

INSERT INTO @temp 
SELECT ROW_NUMBER() over (order by Expr1) as rowNum, * 
from ( 

SELECT  dbo.SOInfoArchive.jobName, 
dbo.SOInfoArchive.nodeID, 
dbo.SOInfoArchive.nodeGroup, 
dbo.SOInfoArchive.endStatus, 
dbo.SOInfoArchive.returnCode, 
dbo.SOInfoArchive.startTime, 
dbo.SOInfoArchive.endTime, 
dbo.SOInfoArchive.oDate, 
dbo.SOInfoArchive.orderID, 
dbo.SOInfoArchive.status, 
dbo.SOInfoArchive.runCount, 
dbo.SOInfoArchive.owner, 
dbo.SOInfoArchive.cyclic, 
dbo.SOInfoArchive.soInfoID, 
dbo.SOInfoArchive.docInfoID, 
dbo.SOInfoArchive.existsNote, 
dbo.SOInfoArchive.noSysout, 
dbo.serverInfo.serverName, 
dbo.Groups.label AS applicationName, 
Groups_1.label AS memberName, 
Groups_2.label AS groupName, 
Groups_3.label AS scheduleTableName, 
dbo.SOInfoArchive.serverInfoID, 
dbo.SOInfoArchive.applicationID, 
dbo.SOInfoArchive.groupID, 
dbo.SOInfoArchive.memberID, 
dbo.SOInfoArchive.scheduleTableID, 
dbo.docFile.docFileID, 
dbo.docInfo.docInfoID AS Expr1, 
dbo.docFile.docFileObject 
FROM   dbo.SOInfoArchive INNER JOIN 
         dbo.serverInfo ON dbo.SOInfoArchive.serverInfoID = dbo.serverInfo.serverInfoID INNER JOIN 
         dbo.docInfo ON dbo.SOInfoArchive.docInfoID = dbo.docInfo.docInfoID INNER JOIN 
         dbo.docFile ON dbo.docInfo.docFileID = dbo.docFile.docFileID LEFT OUTER JOIN 
         dbo.Groups AS Groups_3 ON dbo.SOInfoArchive.scheduleTableID = Groups_3.ID LEFT OUTER JOIN 
         dbo.Groups AS Groups_1 ON dbo.SOInfoArchive.memberID = Groups_1.ID LEFT OUTER JOIN 
         dbo.Groups AS Groups_2 ON dbo.SOInfoArchive.groupID = Groups_2.ID LEFT OUTER JOIN 
         dbo.Groups ON dbo.SOInfoArchive.applicationID = dbo.Groups.ID 

         WHERE CONTAINS (docfileObject,@searchText) 
) tbl 

-- Select enables me to consume the following columns as meta data in EF 

    SELECT rowNum, 
     serverName, 
     jobName , 
      oDate, 
      runCount, 
      orderID, 
      applicationName, 
      memberName, 
      nodeID, 
      endStatus, 
      returnCode, 
      startTime, 
      endTime, 
      status, 
      owner, 
      existsNote, 
      docFileID  
    FROM @temp WHERE rowNum > @LowerLimit AND rowNum <= @UpperLimit 



END 

因此,要回顾一下,我现在可以

  • 1)导入存储过程中进入我的EDMX。

  • 2) “添加函数导入” 创建成功

一)sp_SoInfoDocs函数导入

B)sp_SoInfoDocs复杂类型

我现在可以成功调用我的存储过程如下

 using (TestEntities context = new TestEntities()) 
    { 
      string searchText = "rem"; 
      ObjectParameter total = new ObjectParameter("out",typeof(int)); 

      List<sp_SoInfoDocs_Result> lst = context.sp_SoInfoDocs(searchText, 1, 10, total).ToList(); 

      foreach (var item in lst) 
      { 
      Console.WriteLine(item.jobName + " " + item.oDate + " " + item.serverName + " " + item.startTime + " " + item.endTime); 

      } 
      Console.ReadLine(); 
    } 

还有一个例子, e结果返回。

enter image description here

我现在已经成功地使用这种方法的基础上导入并在我看来,在显示动态创建的HTML表中的元数据。

如果任何人遇到类似的问题,我已经忘了充分解释为什么我采用了这种解决方案,我如何使工作〜然后请随时P.M.我和我会尽力解释。

+0

根本不需要使用#temp_table/table变量。看到我的答案。 – lad2025

0

为什么要使用临时表或表变量。表变量有很多performance drawbacks,如:

Table variables does not have distribution statistics, they will not trigger recompiles. Therefore, in many cases, the optimizer will build a query plan on the assumption that the table variable has no rows. For this reason, you should be cautious about using a table variable if you expect a larger number of rows (greater than 100). Temp tables may be a better solution in this case. Alternatively, for queries that join the table variable with other tables, use the RECOMPILE hint, which will cause the optimizer to use the correct cardinatlity for the table variable.

table variables are not supported in the SQL Server optimizer's cost-based reasoning model. Therefore, they should not be used when cost-based choices are required to achieve an efficient query plan. Temporary tables are preferred when cost-based choices are required. This typically includes queries with joins, parallelism decisions, and index selection choices.

Queries that modify table variables do not generate parallel query execution plans. Performance can be affected when very large table variables, or table variables in complex queries, are modified. In these situations, consider using temporary tables instead. For more information, see CREATE TABLE (Transact-SQL). Queries that read table variables without modifying them can still be parallelized.

使用简单CTE:

ALTER PROCEDURE [dbo].[sp_SoInfoDocs_Archive] 
    @searchText NVARCHAR(200), 
    @PageNumber INT, 
    @PageSize INT, 
    @out  INT = 0 OUTPUT 

AS 
BEGIN 
SET NOCOUNT ON; 
DECLARE @LowerLimit INT = (@PageNumber - 1) * @PageSize; 
DECLARE @UpperLimit INT = @PageNumber * @PageSize; 


;WITH cte AS 
(
    SELECT 
    dbo.SOInfoArchive.jobName, 
    dbo.SOInfoArchive.nodeID, 
    dbo.SOInfoArchive.nodeGroup, 
    dbo.SOInfoArchive.endStatus, 
    dbo.SOInfoArchive.returnCode, 
    dbo.SOInfoArchive.startTime, 
    dbo.SOInfoArchive.endTime, 
    dbo.SOInfoArchive.oDate, 
    dbo.SOInfoArchive.orderID, 
    dbo.SOInfoArchive.status, 
    dbo.SOInfoArchive.runCount, 
    dbo.SOInfoArchive.owner, 
    dbo.SOInfoArchive.cyclic, 
    dbo.SOInfoArchive.soInfoID, 
    dbo.SOInfoArchive.docInfoID, 
    dbo.SOInfoArchive.existsNote, 
    dbo.SOInfoArchive.noSysout, 
    dbo.serverInfo.serverName, 
    dbo.Groups.label AS applicationName, 
    Groups_1.label AS memberName, 
    Groups_2.label AS groupName, 
    Groups_3.label AS scheduleTableName, 
    dbo.SOInfoArchive.serverInfoID, 
    dbo.SOInfoArchive.applicationID, 
    dbo.SOInfoArchive.groupID, 
    dbo.SOInfoArchive.memberID, 
    dbo.SOInfoArchive.scheduleTableID, 
    dbo.docFile.docFileID, 
    dbo.docInfo.docInfoID AS Expr1, 
    dbo.docFile.docFileObject 
    FROM dbo.SOInfoArchive 
    JOIN dbo.serverInfo 
    ON dbo.SOInfoArchive.serverInfoID = dbo.serverInfo.serverInfoID 
    JOIN dbo.docInfo 
    ON dbo.SOInfoArchive.docInfoID = dbo.docInfo.docInfoID 
    JOIN dbo.docFile 
    ON dbo.docInfo.docFileID = dbo.docFile.docFileID 
    LEFT JOIN dbo.Groups AS Groups_3 
    ON dbo.SOInfoArchive.scheduleTableID = Groups_3.ID 
    LEFT JOIN dbo.Groups AS Groups_1 
    ON dbo.SOInfoArchive.memberID = Groups_1.ID 
    LEFT JOIN dbo.Groups AS Groups_2 
    ON dbo.SOInfoArchive.groupID = Groups_2.ID 
    LEFT JOIN dbo.Groups 
    ON dbo.SOInfoArchive.applicationID = dbo.Groups.ID 
    WHERE CONTAINS (docfileObject,@searchText) 
), 
cte2 AS 
(
    SELECT ROW_NUMBER() OVER (ORDER BY Expr1) AS rowNum, * 
    FROM cte 
) 
SELECT rowNum, 
     serverName, 
     jobName , 
     oDate, 
     runCount, 
     orderID, 
     applicationName, 
     memberName, 
     nodeID, 
     endStatus, 
     returnCode, 
     startTime, 
     endTime, 
     status, 
     owner, 
     existsNote, 
     docFileID  
    FROM cte2 
    WHERE rowNum > @LowerLimit 
    AND rowNum <= @UpperLimit 
END 
+0

感谢您的反馈和建议。我按照你的建议创建了存储过程,当我在SQL服务器上手动运行输入变量时,它完美地工作。但是,当我尝试将实体框架导入实体框架时,我现在遇到了问题。我可以导入的SP,将建立功能导入〜但是没有映射,因此它也无法自动bulid复杂类型......,我无法手动生成它们。 –

+0

@ M70-536实体框架与CTE一起工作吗? – lad2025

+0

我已经创建的存储过程如你所说,我在SQL服务器上运行它通过手动输入变量〜它完美的作品。但是,当我尝试将实体框架导入实体框架时,我现在遇到了问题。我可以导入的SP,将建立功能导入〜但是没有映射,因此它也无法自动bulid复杂类型......,我无法手动生成它们 –