7

長年の潜伏者、初めてのポスターはこちら :)

Google などで検索するのに飽きてきたので、ここで質問することにしました。SQL 2005 DB から Web サイト (FW 4.0、C#) LINQ プロジェクトにストアド プロシージャをインポートすると、次のエラーが発生します。

「次のストアド プロシージャの戻り値の型を検出できませんでした」

2 つのクエリがあります。一時テーブルを使用していないことに注意してください。これらのクエリは、セキュリティ対策のために変数名などでのみ編集されています。とにかく、これが機能するものです

ALTER PROCEDURE [dbo].[spMyWorkingProc]
@OS numeric
AS
BEGIN
SET NOCOUNT ON;

DECLARE @sql varchar(5000)

set @sql = '
        SELECT
        *
        FROM MYDB.dbo.MYVIEW 
        WHERE OS = ' + CONVERT(varchar, @OS)

EXEC('
SET NOCOUNT ON
SELECT * FROM
OPENROWSET(''SQLOLEDB'', ''MYDB''; ''user''; ''password'', ''' + @sql + ''')')

END

そして、これはそうではありません

ALTER PROCEDURE [dbo].[spNotWorking]
@IDCLIENT int,
@PPNO char(10)
AS
BEGIN
SET NOCOUNT ON;

DECLARE @sql varchar(5000)

set @sql = '
        SELECT
        *
        FROM MYDB.dbo.MYOTHERVIEW
        WHERE ID = ' + CONVERT(VARCHAR, @IDCLIENT) + ' AND PASSPORTNO = ' + @PPNO + ' ORDER BY AGE'

EXEC('
SET NOCOUNT ON
SELECT * FROM
OPENROWSET(''SQLOLEDB'', ''MYDB''; ''user''; ''password'', ''' + @sql + ''')')  

END

いくつかのメモと質問とともに、私が試して見つけたものは次のとおりです。

  • 両方のユーザー (LINQ とリモート サーバー) が db_owner です。

  • 機能しないストアド プロシージャは、パラメーターを 1 つだけ残しておいても機能します (どのパラメーターでもかまいません)。新しいものを追加しても機能しません。

  • シンプルなselect * from any tableと2つ以上のパラメーターを使用して空のSPを作成すると、機能します(意味がありません)。

  • 問題がEXECにあるとしましょう。もしそうなら、なぜ最初の SP が機能するのですか? わかりました、問題はそこにはありません。(それは論理が教えてくれることだと思いますか?)

  • 作業中の SP でアクセスしたビューを使用すると機能しないため、問題はビューではありません。

  • 提供されたクエリを使用してこれを行う必要があります。6.5データベースに接続するためにこれを行う必要があるため、リンクサーバーなどを使用できません。同じ方法を使用している間、最初のSPが機能し、2番目のSPが機能しない理由を解決または説明しません。

  • パラメータ(非動作SPから取得)を動作SPに追加しようとしましたが、動作するため、2番目のSPで何かする必要がありますが、何がわかりません:/

  • 2 番目の SP を変更し、@VAR のスタイルのパラメーターを削除して、単一の @sql 変数にハードコードすると、完全に機能します。だから、動的クエリ(または何か)に変数を含める必要があると思います。

私は文字通り髪を抜いているので、アイデアや提案は大歓迎です!

前もって感謝します!- ダークガイ

4

3 に答える 3

8

Linq2Sql関数インポートなどの ORM コード生成ツールは通常、結果セットを「スニッフィング」するために、実際に proc を実行せずに、 SHOWPLAN_ALL設定をオンにして SPROC を実行します。

このアプローチには、お気づきのように、動的 SQL に制限があり、TempDB を使用するプロシージャや、異なるスキーマでデータを返すブランチを持つプロシージャにもしばしば問題があります。

あなたの解決策は良いものです。つまり、実際のprocをハードコードされたものに置き換えますが、実際のデータを表すモックデータを返します。

編集

これに対処するために私が見た別のパターンは、次のように、ハードコードされた「スキーマ」の結果を呼び出し不可能な条件に埋め込むことです。

ALTER PROCEDURE [dbo].[someProc]
AS
BEGIN
  SET NOCOUNT ON;
  IF (1 = 0)
    BEGIN
      -- "Cheat" the ORM resultset sniffing by returning an example of the schema.
      -- Casting and name aliasing to ensure the ORM derives the correct types
      SELECT CAST('Hello' AS NVARCHAR(50)) AS Name, CAST (1 AS BIT) AS IsOnline, ...
      RETURN;
    END
    .. rest of the REAL proc goes here
于 2012-08-14T19:55:00.080 に答える
1

以下の形式で proc を記述します。

CREATE PROCEDURE PROC_NAME
@variableName nvarchar(150)
AS
IF 1=0 BEGIN
SET FMTONLY OFF
END
BEGIN
SET NOCOUNT ON;
DECLARE @Sql nvarchar(MAX)
SET @Sql = 'SELECT Column1, Column2, Column3 FROM' ;
EXEC sp_executesql @Sql
END

上記フォーマットの違いは IF 1=0 BEGIN SET FMTONLY OFF END

この問題を解決し、戻り値の型を決定するのに役立ちます。

于 2016-04-21T22:26:24.730 に答える
1

私も同じ問題を抱えていました。多くのサイトをチェックすると、このリンクで言及されている3つのポイントについて述べられていますが、問題の原因となっているトランザクションについてはどこにも言及されていません. 私の場合、地獄を上げたのはトライキャッチブロックでした。それを削除した後、LINQ to SQL は正常に動作しました。後でtry catch backを導入しました。

于 2014-08-29T17:54:29.133 に答える