实体框架4,复杂类型,StoredProcs和临时表的问题

时间:2010-06-15 18:02:30

标签: entity-framework complextype

我在实体框架4上剥了皮,遇到了一个小问题。

我有一些存储过程,我将其添加到EDMX中。当我从这些过程创建复杂类型时,EF获取列信息没有问题。除了在一个地方。在困惑了一段时间后,我发现这是我的临时表填充,导致问题。实际上它只是将INSERT调用到导致问题的临时表中。我实际上并没有用任何信息填充它。

虽然我知道我可以手动创建复杂类型然后将函数映射到该类型,但我希望能够让EF为我处理它。有谁知道我做错了什么?

以下是一个不起作用的示例过程。在DB中运行它并将proc添加到EDMX。然后尝试在“添加功能导入”屏幕中获取列信息。什么都没有归还。将INSERT注释到临时表并获取列信息并且它可以正常工作。

谢谢, 史蒂夫

CREATE PROCEDURE dbo.TestProc
AS

SET NOCOUNT ON  

    CREATE TABLE #TempTable(
        StartDate datetime
    )

    INSERT INTO #TempTable
    SELECT  null


    DROP TABLE #TempTable

    SELECT 1 AS ReturnValue

SET NOCOUNT OFF
GO

3 个答案:

答案 0 :(得分:6)

要尝试的一些事情。

  1. 使用Variable Tables代替 - >也许导入向导更喜欢这个?
  2. 命名您的返回字段。
  3. 尝试使用以下存储过程(未经测试......只是大声思考......)

    CREATE PROCEDURE dbo.Foo
    AS
    
        SET NOCOUNT ON
    
        DECLARE @ResultTable TABLE (SomeId INTEGER)
    
        INSERT INTO @ResultTable
        SELECT DISTINCT Id AS Identity -- Or u can rename this field to anything...
        FROM SomeExistingTableWhichHasAnIdentityField
    
    GO
    

    尝试并立即查看向导是否刷新。

    -

    尝试#2:)

    好的..当EF设计师/向导/无法确切地弄清楚我的存储过程假设要返回的内容时,我通常会执行以下操作: -

    1. 确保EF设计器/上下文等中根本不存在存储过程。(您有一个干净的起点)
    2. 在程序定义后打开存储过程并/* /*注释一切
    3. 例如..

      ALTER PROCEDURE dbo.Foo
      (
          Bar1 INT,
          Bar2 TINYINT,
          ... // whatever u have as your optional input arguments //
      )
      AS
          SET NOCOUNT ON
      
          /* 
          .... every thing in here is commented out 
          */
      GO
      

      现在......   3.在存储过程中添加强制虚假返回,其中(或多或少)只是定义输出结构/字段。

      例如..

      ALTER PROCEDURE dbo.Foo
      (
          Bar1 INT,
          Bar2 TINYINT,
          ... // whatever u have as your optional input arguments //
      )
      AS
          SET NOCOUNT ON
      
          SELECT 1 AS Id, 1 AS UserId, 1 AS SomeOtherId, 
              CAST('AAA' AS NVARCHAR(350)) AS Name,
              -- etc etc etc..
          /* 
          .... every thing in here is commented out 
          */
      GO
      

      and then ...

      1. 将此存储过程添加到EF设计器/向导/等等......现在,设计人员应“确定”正确的字段。真棒。是..这些值都是硬编码的..但是没关系(到目前为止)。
      2. 一旦您对EF现在更新正确感到高兴,请返回到您的存储过程,并删除所有硬编码的SELECT(我们在上面的步骤中做了)。现在我们删除注释掉整个实际代码的注释。所以你应该有你原来的存储过程。
      3. ...现在EF已更新,并且不知道我们已经更改了存储过程的管道。

        胜利:)。

        这适用于你吗?

答案 1 :(得分:1)

这是Pure.Krome的优秀答案的变体。而不是注释掉你的sproc代码,创建一个只包含Pure描述的“假”选择语句的新视图。该视图将用于创建实体。然后,视图实体成为存储过程结果的容器。

Create View dbo.FooWrapperView as 
  Select IsNull(MyPrimaryID,-999) as IntFieldName, --IsNull disallows nulls so EF designer will make this the primary key.
  NullIf(CAST('AAA' as VarChar(20)), '') as VarChar20FieldName, --NullIf allows null so EF designer will NOT make this part of the primary key.
  NullIf(CAST('AAA' as VarChar(42)), '') as VarChar42FieldName,
  NullIf(CAST(1.1 as DECIMAL(8, 5)), '') as Decimal85FieldName

在实体设计器中右键单击并选择“从数据库更新模型”,然后选择包装器视图(如果尚未选择,则选择sproc)。这将创建映射到伪造包装器视图的实体。设计者根据视图的IsNull和NullIf语句(details here)选择主键。在模型浏览器中找到sproc。右键单击它并选择“添加函数导入...”。在“返回一个集合”下选择实体。选择视图实体,然后单击“确定”。现在,当您调用存储过程时,它会将结果转储到您的视图实体中。

MyProject.MyEntities myContext = new MyProject.MyEntities();
var myQuery = myContext.usp_FOO(myRecordID);
FooWrapperViewEntity myFooEntity = new FooWrapperViewEntity();
myFooEntity = myQuery.FirstOrDefault();

答案 2 :(得分:0)

首先,您必须在不使用临时表的情况下创建正常的存储过程。此存储过程将包含所有列名称(普通表+临时表)。现在可以在EDMX中创建复杂类型

For more see this