2011-12-09 19 views
15

tôi là tạo ra một ứng dụng mới mà cần phải giao tiếp với mã di sản :(.EF ExecuteStoredCommand với returnValue tham số

Các thủ tục lưu trữ Tôi đang cố gắng để gọi sử dụng RETURN cho kết quả của nó. Nỗ lực của tôi để thực hiện và tiêu thụ kết quả giá trị trả về trong ngoại lệ:

InvalidOperationException:. Khi thực hiện một lệnh, các thông số phải được độc quyền các thông số cơ sở dữ liệu hoặc giá trị

Thay đổi proc lưu trữ để trả lại valu e một cách khác là không mong muốn, vì nó hoặc là yêu cầu cập nhật các ứng dụng di sản hoặc duy trì một proc gần như trùng lặp được lưu trữ.

Di sản được lưu trữ proc tóm tắt:

DECLARE @MyID INT 
INSERT INTO MyTable ... 
SELECT @MyID = IDENTITY() 
RETURN @MyID 

My Entity Framework/DbContext làm việc, trong đó sản lượng các InvalidOperationException trên.

SqlParameter parm = new SqlParameter() { 
    ParameterName = "@MyID", 
    Direction = System.Data.ParameterDirection.ReturnValue 
}; 

DbContext.Database.ExecuteSqlCommand("EXEC dbo.MyProc", parm); 

Tìm bất kỳ và tất cả các giải pháp không yêu cầu sửa đổi được lưu trữ.

Trả lời

-2

Tôi chắc chắn đây không phải là câu trả lời hợp lệ duy nhất, mà là câu trả lời cuối cùng tôi đã sử dụng và đã hoạt động thành công.

Phím dường như đặt tên cho tham số ReturnValue RetVal.

SqlParameter id = create.Parameters.Add("RetVal", System.Data.SqlDbType.Int); 
id.Direction = System.Data.ParameterDirection.ReturnValue; 

đặt nó tất cả cùng nhau:

SqlCommand proc = new SqlCommand("dbo.MyProc", new SqlConnection(<connection string>)); 
proc.CommandType = System.Data.CommandType.StoredProcedure; 

SqlParameter id = create.Parameters.Add("RetVal", System.Data.SqlDbType.Int); 
id.Direction = System.Data.ParameterDirection.ReturnValue; 

proc.ExecuteNonQuery(); 

int newId = Convert.ToInt32(id.Value); 
+2

những gì được tạo ra ở đây? –

2

Bạn không để sử dụng ExecuteSqlCommand.

Bạn chỉ có thể nhận được các kết nối cơ bản từ DbContext.Database.Connection và sử dụng ADO.NET thô (CreateCommand(), ExecuteNonQuery() ...)

25

Bạn có thể nắm bắt được giá trị trả về của thủ tục lưu trữ vào một tham số đầu ra thay vì:

SqlParameter parm = new SqlParameter() { 
    ParameterName = "@MyID", 
    SqlDbType = SqlDbType.Int, 
    Direction = System.Data.ParameterDirection.Output 
}; 

Database.ExecuteSqlCommand("exec @MyId = dbo.MyProc", parm); 

int id = (int)parm.Value; 
0

Tạo bảng cho Ví dụ tham số để kiểm tra hoặc thay đổi truy vấn sql thứ hai theo truy vấn của bạn.

CREATE TABLE [dbo].[Test](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [Name] [varchar](50) NOT NULL, 
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

// ========================= =============== ================== //

 public void Test() 
     { 
        using (var db = new DbContext()) 
        { 
         string sql = "dbo.MyProc"; //With Out Parameter 

        int id1 = (int)db.Database.SqlQuery<decimal>(sql).FirstOrDefault(); 
        db.SaveChanges(); 

        //Or 

        sql = "INSERT Test(Name) values({0}) SELECT SCOPE_IDENTITY();"; //With Parameter 
        int id2 = (int)db.Database.SqlQuery<decimal>(sql, new object[] { "Thulasi Ram.S" }).FirstOrDefault(); 
        db.SaveChanges(); 
       } 
     } 
+0

tôi có thể có thể nhận được id chính bởi mã trên. – Thulasiram

0

lỗi nhắn

InvalidOperationException: Khi thực hiện một lệnh, các thông số phải được độc quyền các thông số cơ sở dữ liệu hoặc giá trị.

có nghĩa là bạn không cung cấp đúng loại (hoặc cái gì khác không được hiển thị trong đoạn mã của bạn) trong danh sách params của SQLParameters.

Trong trường hợp của tôi, tôi đã quên xóa một MergeOption vì tôi đã thay đổi cách lệnh SQL được thực hiện.

0

Tôi đã thử các cách trên, nhưng cách duy nhất này hoạt động ra cho tôi (Phải có 'ToList()' chức năng):

SqlParameter res = new SqlParameter() 
     { 
      ParameterName = "Count", 
      Value=1, 
      Direction = System.Data.ParameterDirection.Output 
     }; 
db.Database.SqlQuery<object>(
     "[dbo].[GetWorkerCountBySearchConditions] @Count , 
     res 
     ).ToList(); 
     return Convert.ToInt32(res.Value); 
0

Điều này extension method sẽ thực hiện tất cả công việc bẩn thỉu cho bạn ngay bây giờ. Xem mô tả đầy đủ hơn về SO here.

-1

này sẽ trở lại với int từ một proc lưu trữ sử dụng DBContext:

var newId = DbContext.Database.SqlQuery<int>("EXEC dbo.MyProc @MyID = {0}", parm).First(); 
+3

Đây là đề xuất _terrible_. Mã này là dễ bị tấn công SQL injection. ** Rất hiếm khi ** là loại tuyên bố xây dựng và thực hiện một ý tưởng tốt. Luôn cố gắng sử dụng truy vấn được tham số hóa. – NathanAldenSr

+0

@NathanAldenSr - phương thức 'SqlQuery' tự động chuyển đổi các tham số mà bạn cung cấp thành DbParameters. Đây là một truy vấn được tham số hóa - nó phải là để gọi một thủ tục lưu sẵn có tham số. https://msdn.microsoft.com/en-us/library/system.data.entity.database.sqlquery(v=vs.113).aspx – Colin

+0

@Colin Ah, lỗi của tôi vì không hiểu rõ hơn về phương pháp đó. – NathanAldenSr

1

Tôi biết đó là một hơi muộn, nhưng hoạt động này đối với tôi:

var param = new SqlParameter("@Parameter1", txtBoxORsmth.text); 

someVariable = ctx.Database.SqlQuery<int>("EXEC dbo.MyProc", param).First(); 
+0

Nó không hoạt động cho các tham số đầu ra –