0

これは私が使用しているサンプルのストアドプロシージャです

CREATE PROCEDURE [dbo].[CreateCustomer]
        @firstName nvarchar(50) = null,
        @lastName nvarchar(50) = null,
        @emailAddress nvarchar(50),
        @contactNumber varchar(15) =null,
        @street1 nvarchar(50) = null,
        @street2 nvarchar(50) = null,
        @city nvarchar(50) = null,
        @State nvarchar(50)= null,
        @Country nvarchar(50)=null,
        @postalCode varchar(5) = null,
        @middleName nvarchar(50),
        @password nvarchar(50),
        @membershipExpieryDate datetime,
        @status int OUT

    AS
        BEGIN TRY
            BEGIN TRANSACTION
            SAVE TRANSACTION initialP
                DECLARE @lastAccessed datetime = GETDATE()
                DEClARE @uniqueCustomerID UNIQUEIDENTIFIER= NEWID()
                BEGIN TRANSACTION
                    INSERT INTO Customers(CustomerID, FirstName, LastName, EmailAddress, LastAccessed, ContactNumber, 
                        Street1, Street2, City, State, Country, PostalCode, MiddleName, Password, MembershipExpieryDate)
                        VALUES(@uniqueCustomerID,@firstName, @lastName, @emailAddress, @lastAccessed, @contactNumber, @street1, @street2,
                         @city, @State, @Country, @postalCode, @middleName, @password, @membershipExpieryDate)



     INSERT INTO Roles(CustomersCustomerID,Role) VALUES(@uniqueCustomerID,'V') 
            COMMIT

            SELECT CustomerID, FirstName, LastName, EmailAddress, LastAccessed, ContactNumber, 
                Street1, Street2, City, State, Country, PostalCode, MiddleName, MembershipExpieryDate FROM Customers WHERE EmailAddress = @emailAddress  

        SET @status =1
        COMMIT
    END TRY 
    BEGIN CATCH
        IF(@@TRANCOUNT > 0)
        BEGIN
            ROLLBACK TRANSACTION initialP
        END
        SET @status =2
    END CATCH

そして、これは私がクエリデータを取得するために使用しているコードです:

ObjectParameter status = new ObjectParameter("status", typeof(int));
var dataSet = Entity.CreateCustomer(newCustomer.FirstName, newCustomer.LastName,
newCustomer.EmailAddress, newCustomer.ContactNumber, newCustomer.Street1, newCustomer.Street2,
newCustomer.City, newCustomer.State, newCustomer.Country, newCustomer.PostalCode, newCustomer.MiddleName,
newCustomer.Password, newCustomer.MembershipExpieryDate, status);

ただし、このストアドプロシージャを実行すると、トランスカウントの不一致というエラーが発生します。私が知っているように、trans countは発生すると1ずつbegin transaction増加し、発生すると1つ減少しcommitます。複合型を返す可能性があるため、関数importで関数を既にマップしました。

これで問題がわかりません。私にはそれは大丈夫のようです。私はこれを正しくやっているかどうか、いくつかの詳細で天気を知りたいです。ありがとう。

編集:これは私がサンプルコードを書くことによって見つけたものです。私は最初、トランスアクションを開始してコミットすることだと思いました。そうではありません。commitステートメントの前でも挿入される値を選択できます(間違っている場合は修正してください)。3つの列(test1の一意の識別子、test2 int、test3 int)を持つテストテーブルを作成し、ストアドプロシージャ呼び出しTestを作成しました。以下に示します。

CREATE PROCEDURE dbo.TestForCommit

    (
    @test11 int,
    @test111 int,
    @status int OUTPUT
    )

AS
    begin try
        declare @test1 uniqueidentifier  = NEWID()
        begin transaction
            insert into TestT1(Test1, Test11, Test111) values(@test1, @test11, @test111)
        commit
        select Test1, Test11, Test111 from TestT1 where Test1 = @test1
        SET @status = 1
    end try
    begin catch
        Rollback Transaction
        set @status =2
    end catch
    /* SET NOCOUNT ON */
    RETURN

エンティティモデルので機能インポートを作成し、次のように使用しました。

            ObjectParameter status = new ObjectParameter("status", typeof(int));
            SchoolEntities test = new SchoolEntities();
            var dataSet = test.TestForCommit(1, 1, status);
                //A:
                //(XXXXXXXXXXXXX)Console.WriteLine((int)status.Value);
                foreach (var item in dataSet)
                {
                    TestForCommit_Result t = item;
                    Console.WriteLine("{0} , {1} , {2}", t.Test1, t.Test11, t.Test111);

                }
                //B:
                Console.WriteLine((int)status.Value);
                Console.ReadLine();

この//A:部分が問題を引き起こしています。これにより、null参照例外が発生します。ただし、// B:パーツは機能しており、ステータス値を示しています。私はまだそれがそのように機能している理由を探しています。ありがとう!!

4

1 に答える 1

1

私のおすすめ。(Xact_Abortをオンに設定)

Begin Try
    Set NoCount On
    Set Xact_Abort On
    Begin Tran
        --Your Query
    Commit Tran
End Try

Begin Catch
    Rollback Tran
End Catch

CREATE PROCEDURE [dbo].[CreateCustomer]
    @firstName nvarchar(50) = null,
    @lastName nvarchar(50) = null,
    @emailAddress nvarchar(50),
    @contactNumber varchar(15) =null,
    @street1 nvarchar(50) = null,
    @street2 nvarchar(50) = null,
    @city nvarchar(50) = null,
    @State nvarchar(50)= null,
    @Country nvarchar(50)=null,
    @postalCode varchar(5) = null,
    @middleName nvarchar(50),
    @password nvarchar(50),
    @membershipExpieryDate datetime,
    @status int OUT

AS
BEGIN TRY
    Set NoCount ON
    Set XAct_Abort ON
    DECLARE @lastAccessed datetime = GETDATE()
    DEClARE @uniqueCustomerID UNIQUEIDENTIFIER= NEWID()

    BEGIN TRANSACTION
    INSERT INTO Customers(CustomerID, FirstName, LastName, EmailAddress, LastAccessed, ContactNumber, 
    Street1, Street2, City, State, Country, PostalCode, MiddleName, Password, MembershipExpieryDate)
    VALUES(@uniqueCustomerID,@firstName, @lastName, @emailAddress, @lastAccessed, @contactNumber, @street1, @street2,
    @city, @State, @Country, @postalCode, @middleName, @password, @membershipExpieryDate)

    INSERT INTO Roles(CustomersCustomerID,Role) VALUES(@uniqueCustomerID,'V') 
    COMMIT

    SELECT CustomerID, FirstName, LastName, EmailAddress, LastAccessed, ContactNumber, 
    Street1, Street2, City, State, Country, PostalCode, MiddleName, MembershipExpieryDate FROM Customers WHERE EmailAddress = @emailAddress  

    SET @status =1
    COMMIT Tran
END TRY 
BEGIN CATCH
    ROLLBACK TRANSACTION
    SET @status =2
END CATCH
于 2012-07-30T10:55:39.000 に答える