4

私にはアカウント作成プロセスがあり、基本的にユーザーがサインアップするときに、複数のテーブル、つまりユーザー、プロファイル、アドレスにエントリを作成する必要があります。Userテーブルに1つのエントリ、Profileに1つのエントリ、Addressテーブルに2〜3のエントリがあります。したがって、最大で5つのエントリがあります。私の質問は、これのXMLをストアドプロシージャに渡してそこで解析する必要がありますか、それともC#コードでトランザクションオブジェクトを作成し、接続を開いたままにして、アドレスを1つずつループに挿入する必要がありますか?

このシナリオにどのようにアプローチしますか?接続が開いていても、複数の呼び出しを行うとパフォーマンスが低下する可能性がありますか?

4

4 に答える 4

6

不快感はありませんが、あなたはこれを考えすぎています。

情報を収集し、すべてをまとめたら、トランザクションを作成して、新しい行を1つずつ挿入します。トランザクションは短命であるため、ここではパフォーマンスに影響はありません。

問題は、接続でトランザクションを作成し、ユーザー行を挿入してから、ユーザーがさらにプロファイル情報を入力するのを待ってから、それを挿入してから、アドレス情報が追加されるのを待ってから、それを挿入する場合です。これは行わないでください。これは不必要に長時間実行されるトランザクションであり、問​​題が発生します。

ただし、シナリオ(すべてのデータがある場合)はトランザクションの正しい使用法であり、データの整合性を確保し、データベースに負担をかけず、それ自体でデッドロックを引き起こすことはありません。

お役に立てれば。

PS Xmlアプローチの欠点は、複雑さが増すことです。コードはxmlのスキーマを知る必要があり、ストアドプロシージャはXmlスキーマも知る必要があります。ストアドプロシージャには、xmlを解析してから、行を挿入するという複雑さが加わります。単純な短期間のトランザクションが複雑であるという利点は、実際にはわかりません。

于 2012-04-24T09:45:48.600 に答える
5

複数のテーブルにレコードを挿入する場合は、XMLパラメーターの使用は複雑な方法です。.netでXmlを作成し、3つの異なるテーブルのxmlからレコードを抽出することは、SQLServerでは複雑です。

トランザクション内でクエリを実行するのは簡単な方法ですが、.netコードとSQ​​Lサーバーを切り替えるためにパフォーマンスが低下する場合があります。

最善のアプローチは、ストアドプロシージャでテーブルパラメータを使用することです。.netコードで3つのデータテーブルを作成し、それらをストアドプロシージャに渡します。

-挿入する必要のあるすべてのフィールドを含むテーブルのタイプごとに、タイプTargetUDT1、TargetUDT2、およびTargetUDT3を作成します

CREATE TYPE [TargetUDT1] AS TABLE
             (
             [FirstName] [varchar](100)NOT NULL,
             [LastName] [varchar](100)NOT NULL,
             [Email] [varchar](200) NOT NULL
             )

-次に、次の方法でspを書き留めます。

 CREATE PROCEDURE AddToTarget(
     @TargetUDT1 TargetUDT1 READONLY,
     @TargetUDT2 TargetUDT2 READONLY,
     @TargetUDT3 TargetUDT3 READONLY)
     AS
 BEGIN
       INSERT INTO [Target1]
       SELECT * FROM @TargetUDT1

       INSERT INTO [Target2]
       SELECT * FROM @TargetUDT2

       INSERT INTO [Target3]
       SELECT * FROM @TargetUDT3
 END

.Netで、3つのデータテーブルを作成して値を入力し、通常どおりspを呼び出します。

于 2012-04-24T10:07:16.690 に答える
0

たとえば、xmlを次のように想定します

<StoredProcedure>
<User>
 <UserName></UserName>
</User>
<Profile>
 <FirstName></FirstName>
</Profile>
<Address>
 <Data></Data>
 <Data></Data>
 <Data></Data>
</Address>
</StoredProcedure>
 

これはストアドプロシージャになります

INSERT INTO Users (UserName) SELECT(UserName) FROM OPENXML(@idoc,'StoredProcedure/User',2)
WITH ( UserName NVARCHAR(256))

ここで、これはidoc変数値を提供し、@docはストアドプロシージャへの入力です。

DECLARE @idoc INT

--Create an internal representation of the XML document.        
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc

同様の手法を使用して、単一のストアドプロシージャで3つの挿入を実行します。これはデータベースへの1回の呼び出しであり、このストアドプロシージャへの1回の呼び出しで複数のアドレス要素が挿入されることに注意してください。

アップデート

ここであなたを誤解させないために、あなたが何をしようとしているのかを理解するための完全なストアドプロシージャがあります

USE [DBNAME]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO  
CREATE PROCEDURE [dbo].[procedure_name]
    @doc [ntext]
WITH EXECUTE AS CALLER
AS
DECLARE @idoc INT  
DECLARE @RowCount INT
SET @ErrorProfile = 0

--Create an internal representation of the XML document.
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc

BEGIN TRANSACTION

INSERT INTO Users (UserName)
SELECT UserName FROM OPENXML(@idoc,'StoredProcedure/User',2)
WITH ( UserName NVARCHAR(256) )

-- Insert Address

-- Insert Profile


SELECT @ErrorProfile = @@Error                              

IF @ErrorProfile = 0
    BEGIN
            COMMIT TRAN
    END
ELSE
    BEGIN
            ROLLBACK TRAN
    END

EXEC sp_xml_removedocument @idoc   
于 2012-04-24T09:49:35.077 に答える
0

パフォーマンスの問題に気づいたことがありますか。あなたがやろうとしていることは非常に簡単で、多くのアプリケーションが毎日毎日行っています。時期尚早の最適化に引き込まれないように注意してください。

新しいトランザクションスコープを作成し、接続を開き、挿入を実行し、トランザクションをコミットして、最後にすべてを破棄することを提案したので、データベースの挿入は非常に安価である必要があります。

using (var tran = new TransactionScope())
using (var conn = new SqlConnection(YourConnectionString))
using (var insetCommand1 = conn.CreateCommand())
using (var insetCommand2 = conn.CreateCommand())
{
    insetCommand1.CommandText = \\SQL to insert

    insetCommand2.CommandText = \\SQL to insert

    insetCommand1.ExecuteNonQuery();

    insetCommand2.ExecuteNonQuery();

    tran.Complete();
}

すべてのロジックをストアドプロシージャにバンドルし、XMLを使用すると複雑さが増し、データベースにロジックを追加する必要があります。エンティティをXML BLOBに変換する必要があり、コードの単体テストが難しくなります。

コードを使いやすくするためにできることはたくさんあります。最初のステップは、データベースロジックを再利用可能なデータベースレイヤーにプッシュし、リポジトリの概念を使用してデータベースからオブジェクトを読み書きすることです。

もちろん、あなたの生活をずっと楽にして、利用可能なORM(オブジェクトリレーショナルマッピング)ライブラリのいずれかを見ることができます。彼らはデータベースと話すことの苦痛を取り除き、あなたのためにそれを処理します。

于 2012-04-24T11:01:22.890 に答える