【问题标题】:Adding stored procedures complex types in Entity Framework在实体框架中添加存储过程复杂类型
【发布时间】:2012-10-01 18:16:56
【问题描述】:

我正在尝试在实体框架中使用不返回任何内容的存储过程。

我做了以下事情:

  1. 添加了一个函数(存储过程右键->添加->函数导入->复杂类型->获取列信息->新建复杂类型)

  2. 我的函数名:summarySP_Result。构建项目后在Generated_codeBusinessAccount.web.g.cs)中没有生成实体类

但是表和视图的实体类都是创建的,但不是存储过程。

谁能给出BusinessAccount.web.g.cs中没有生成实体类的想法?

更新:

让我确认在您的XXXXXX.web.g.cs 类中创建的ReturnDataFromTemTable_result 实体类。

喜欢:

[DataContract(Namespace="http://schemas.datacontract.org/2004/07/BizFramework.Web.Model")]
public sealed partial class ReturnDataFromTemTable_Result : Entity
{
   -------------------
 }

【问题讨论】:

  • 我怀疑存储过程可能是生成类的源,它应该创建一个函数,我错了吗?
  • 对不起,我不知道我是 EF 的新手。(它不会为存储过程创建任何东西。)
  • 在 SP 中它正在选择临时表。在我的 sp 结束时,我写了 select * from @Temp。现在我在 EF 中更新 SP。现在我希望它必须为 SP 创建实体类。但它没有创建。

标签: c# stored-procedures entity-framework-4 silverlight-4.0


【解决方案1】:

好的 - 这是执行此操作的分步方法:

(1) 将您的存储过程添加到 EDMX 文件中(当您第一次创建它时,或者稍后使用Update model from database 并选择该存储过程)

(2) 一旦你的模型中有存储过程 - 使用 Model Browser 添加一个 Function Import

(3) 弹出的下一个对话框非常重要 - 您需要 (1) 定义存储过程返回复杂类型的集合,然后您需要 (2) 从该存储过程中获取列信息以知道它将返回哪些列,然后 (3) 告诉 Visual Studio 根据该列信息生成一个新的复杂类型:

(4) 完成此操作后,您现在应该在模型浏览器的概念模型部分看到存储过程,并且新生成的复杂类型也应该显示在那里:

【讨论】:

  • 谢谢你的回复,马克!你告诉我的我已经做到了。再次查看我的问题。
  • 即使在我强制我的 SP 返回一些列之后,获取列信息也不起作用。我错过了什么吗?
  • 我遇到与@RossBrigoli 相同的问题当我单击“获取列信息”时,它什么也不返回。我们缺少什么?
  • 如果您仍然无法使用这种方法,请考虑此处的答案:stackoverflow.com/q/5996887/529544。 EF 将使用 NULL 参数执行您的 SPROC,以尝试查找结果类型。确保您获得了预期的结果并且您的 SPROC 是正确的
  • 不要忘记 Ctrl-S 并保存您的 edmx 更改。保存并让 VS 返回代码后,我的错误就消失了
【解决方案2】:

这是给罗斯·布里戈利的

尝试将此行添加到存储过程的开头:

设置 FMTONLY 关闭 您可以在完成导入后将其删除。

来源:- Why can't Entity Framework see my Stored Procedure's column information?

【讨论】:

  • 我已经完成了,请看这里:stackoverflow.com/questions/24919046/… 我仍然无法获得想要的结果。你能告诉我更多关于这方面的信息吗?
  • @Termato 下面是我如何通过多个参数实现搜索,由于记录不会超过 7K,它对我来说非常有效。
【解决方案3】:

如果这仍未解决,在添加函数导入后,转到解决方案资源管理器,右键单击您的 {name}.Context.tt 文件并执行“运行自定义工具”。该方法现在将显示在派生的 Context 类中。

这似乎是我正在使用的 Visual Studio 2012 中的一个错误,我还没有应用更新 1,我会尝试看看是否能修复它。

【讨论】:

  • 我不知道为什么,但我这样做了,但我的复杂数据类型中仍然没有显示任何内容。
  • @Chris Amelinckx 感谢您的解决方案。
【解决方案4】:

正如桑迪普所说, EF 不支持导入从动态查询或临时表构建结果集的存储过程。

但您不必重写整个 SP。

只需编写另一个名称相同的代码,它会返回正确的行格式,而无需使用动态 SQL 或临时表。然后使用 EF SP 添加功能,现在将自动生成复杂类型。

编辑:实际上更容易在 SP 的顶部添加注释,该注释可以立即选择所需的行,其中包含使用 CASTS 指定的所有数据类型。当您需要将 SP 导入 EF 时,只需取消注释代码即可。

例如

创建过程 myProc ()
作为
开始
-- 取消注释要导入的以下行:
-- SELECT CAST(0 AS int) AS column1Name, CAST('a' AS varchar(50)) AS clumn2name

-- 导入时将SP内容注释掉。

结束

然后删除存储的过程并创建原始过程。
不过,请保存您制作的临时导入 SP,以备不时之需。

【讨论】:

  • 感谢您有勇气发布此内容。效果很好!
【解决方案5】:

EF 不支持导入从以下位置构建结果集的存储过程:

  • 动态查询
  • 临时表

重写您的存储过程以改用表变量。 请记住在更新之前从模型中删除存储过程和函数导入,因为它不会生成复杂类型,除非它还添加了存储过程。或者在更新存储过程后转到函数导入属性并使用获取列信息功能。

【讨论】:

    【解决方案6】:
    create procedure [dbo].[usp_InsertOrUpdate]
    /*if your table(tbl_InsertOrUpdate) as 3 columns like uniqueid,col1,col2*/
    @uniqueId bigint NULL,/*if insert send value as null or 0*/
    @col1 bigint null,
    @col2 [varchar](500) NULL
    as
    begin
    set nocount ON
    SET FMTONLY OFF
    /* for giving result which column updated(uniqueId) and is it insert or update(IsInsert)*/
    declare @varResult table (uniqueId bigint ,IsInsert bit )
    /*create a var table before inserting original table*/
    
    declare @varInsertOrUpdate table (
    uniqueId bigint ,
    col1 [bigint] ,
    col2 [varchar]
    )
    /*default we are feel as update only*/
    insert into @varResult (uniqueId,IsInsert) values (@uniqueId,0)
    /*insert into var table*/
    INSERT INTO @varInsertOrUpdate (uniqueId,col1,col2)
    VALUES
    (@uniqueId,@col1,@col2)
    /*Insert into original table with where condition without if else*/
     INSERT INTO tbl_InsertOrUpdate (col1,col2)
     select col1,col2 from @varInsertOrUpdate
     where uniqueId!=0;
    /*if its insert updating result returning table*/
     update @varResult set 
     uniqueId=IDENT_CURRENT('tbl_InsertOrUpdate'),
    IsInsert=1 where @uniqueId=0;
    /*updating table where @uniqueid is  null or empty*/
    UPDATE tbl_InsertOrUpdate
    SET col1=@col1, 
    col2=@col2,
    WHERE uniqueId=@uniqueId and @uniqueId!=0
    
    select *  from @varResult
    
    end
    

    【讨论】:

      【解决方案7】:

      要正确添加复杂类型,请转到模型浏览器,右键单击功能,然后显示编辑,单击编辑并填充对话框。函数的名称应与存储过程的名称相同。单击确定按钮。现在函数已创建。然后右键单击创建的函数并再次进行编辑。复杂类型按钮旁边有一个更新按钮。使用该更新按钮对其进行更新。现在复杂类型已完全创建。

      【讨论】:

        【解决方案8】:

        这是我实现多重搜索的 SP

        ***************************************************
        
            CREATE PROCEDURE [dbo].[uspSEARCH_POSITIONS]
                @OBJ_TYPE_REQUEST varchar(2000),--'FIRST_NAME;SEARCHVALUE|LAST_NAME;SEARCHVALUE|JOB_DESCRIPTION;SEARCHVALUE'
                @DELIMITER varchar(10) --'| Which seperates the col;searchvalue|col;searchvalue
            AS
            BEGIN
            SET FMTONLY OFF
                DECLARE
                    @lLastName varchar(100),
                    @lFirstName varchar(100),
                    @lPositionNumber varchar(20),
                    @lJobDescription varchar(50),
                    @lJobCode varchar(20),
                    @lOccupancyIndicator varchar(50),
                    @ldeleimitercolsearchval varchar(10)
        
            SET @ldeleimitercolsearchval =';'
        
            CREATE TABLE #TempTable (ColSearchValues VARCHAR(2000))
        
            INSERT INTO #TempTable 
            SELECT * FROM [dbo].[fnSplit](@OBJ_TYPE_REQUEST,@DELIMITER)--'fname;searchvalfname|lname;searchvallname|jobcode;searchvaljobcode','|')
        
            SELECT @lLastName=SUBSTRING(ColSearchValues,CHARINDEX(@ldeleimitercolsearchval ,ColSearchValues)+1,LEN(ColSearchValues)) from #TempTable where lower(ColSearchValues) like '%last%'
            SELECT @lFirstName =SUBSTRING(ColSearchValues,CHARINDEX(@ldeleimitercolsearchval ,ColSearchValues)+1,LEN(ColSearchValues)) from #TempTable where lower(ColSearchValues) like '%first%'
            SELECT @lPositionNumber =SUBSTRING(ColSearchValues,CHARINDEX(@ldeleimitercolsearchval ,ColSearchValues)+1,LEN(ColSearchValues)) from #TempTable where lower(ColSearchValues) like '%position%'
            SELECT @lJobDescription=SUBSTRING(ColSearchValues,CHARINDEX(@ldeleimitercolsearchval ,ColSearchValues)+1,LEN(ColSearchValues)) from #TempTable where lower(ColSearchValues) like '%jobd%'
            SELECT @lJobCode=SUBSTRING(ColSearchValues,CHARINDEX(@ldeleimitercolsearchval ,ColSearchValues)+1,LEN(ColSearchValues)) from #TempTable where lower(ColSearchValues) like '%jobc%'
            SELECT @lOccupancyIndicator=SUBSTRING(ColSearchValues,CHARINDEX(@ldeleimitercolsearchval ,ColSearchValues)+1,LEN(ColSearchValues)) from #TempTable where lower(ColSearchValues) like '%ccupancy%'
        
                   SELECT  [PS].[POSITION_NUMBER]
                  ,[PS].[COST_CENTER]
                  ,[PS].[JOB_CODE]
                  ,[PS].[JOB_CODE_DESCRIPTION]
                  ,[PS].[SITE_CODE]
                  ,[EMP].[EMPLOYEE_ID]
                  ,[EMP].[EIN]
                  ,[EMP].[GRADE]
                  ,[EMP].[LOGIN_ID]
                  ,[EMP].[FIRST_NAME]
                  ,[EMP].[LAST_NAME]
                  ,LTRIM(RTRIM(ISNULL([EMP].[LAST_NAME],''))) + ',' +LTRIM(RTRIM(ISNULL([EMP].[FIRST_NAME],''))) AS [FULL_NAME]      
                  ,[EMP].[DISTRICT]
                  ,[EMP].[SUPERVISOR_EIN]
                  ,COUNT(*) OVER() AS TOTAL_RECORD_COUNT
              FROM [DBSERVER].[dbo].[uvwPOSITION_SEARCH] PS
              LEFT JOIN [DBSERVER].[dbo].[uvwEMPLOYEES] EMP
              ON PS.POSITION_NUMBER=EMP.POSITION_NUMBER
              WHERE
                    (@lLastName  IS NULL OR [LAST_NAME] LIKE '%' + @lLastName + '%')
                AND (@lFirstName IS NULL OR [FIRST_NAME] LIKE '%' + @lFirstName + '%')
                AND (@lPositionNumber IS NULL OR [PS].[POSITION_NUMBER] LIKE '%' + @lPositionNumber + '%')
                AND (@lJobDescription IS NULL OR [PS].[JOB_CODE_DESCRIPTION] LIKE '%' + @lJobDescription + '%')
                AND (@lJobCode IS NULL OR [PS].[JOB_CODE] LIKE '%' + @lJobCode + '%')
                AND (@lOccupancyIndicator IS NULL OR [EMP].[FILLED_VACANT] LIKE '%' + @lOccupancyIndicator + '%')
        
            END
        

        现在你可以在 edmx 中使用下面的 SP 来消费

        Adding stored procedures complex types in Entity Framework

        Why can't Entity Framework see my Stored Procedure's column information?

        如果您必须更新以下对我有用的 SP。 如果存储过程更新,则更新复杂类型 How Do I Get Entity Framework To Update Complex Types?

        【讨论】:

        • 感谢您提供的信息。这将非常有帮助!
        【解决方案9】:

        对我来说,我在将我的存储过程导入 EF 时遇到问题,不会(自动)生成复杂实体返回对象。然而,我发现,在注释掉我的存储过程(又名存储过程)的部分之后,当我重新导入存储过程(即使用函数导入编辑屏幕中的获取列信息按钮刷新)时,复杂类型然后就可以生成了!

        简而言之,可能有一个 where 子句(或者可能是其他东西)导致 EF 不生成复杂类型。尝试注释掉存储过程的部分并将存储过程重新导入到

        更新:

        在我上面的进一步调查中,我发现没有生成复杂实体的原因是因为我的存储过程使用的是视图(而不是典型的表)。出于好奇,我将视图更改为另一个表只是为了看看会发生什么,以及生成的复杂实体。

        因此,简而言之,如果您有视图,复杂实体可能不会自动生成。为了尝试,我暂时删除了视图,重新导入存储过程,生成复杂实体,然后将视图放回原处。但是现在我的代码给出了异常。

        稍后我会在了解更多信息时对此进行更新 =)

        更新:

        解决了这个问题。真是愚蠢的错误!我使用的视图名称拼写不正确 =D。我有点生气,当我创建存储过程时 Sql Server 没有抛出错误.....我想这就是生活 :) 唉,问题现在解决了!

        【讨论】:

          【解决方案10】:

          复杂类型未出现的问题也可能由于不同的原因而发生,这也是我在我们的案例中遇到的问题。问题是由于 SPROC 中的语法错误,其中临时表定义如下 - 创建表#temp( col1 整数, col2 nvarchar(100), col3 nvarchar(100), -- 注意最后的逗号 ); 令人惊讶的是,当您编译存储过程时,SQL Server 不会抛出任何错误。删除逗号为我们解决了问题。

          简而言之,虽然上述一些解决方案可能会根据具体问题起作用,但我的建议是检查您的存储过程中是否存在 SQL 可能会忽略但可能是导致此问题的根本原因的语法错误。谢谢。

          【讨论】:

            【解决方案11】:

            转到模型浏览器

            如果需要修改现有功能

            在函数导入下>>选择要修改的函数>>点击编辑

            你需要更新函数来刷新,你可以看到需要添加的列

            【讨论】:

              猜你喜欢
              • 2016-04-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多