2010-10-01 36 views
9

Tôi đang sử dụng khung pháp nhân 4.FunctionImport trong khung thực thể 4 issue

Tôi có một thủ tục được lưu trữ chỉ cập nhật một giá trị trong bảng, cụ thể là ID trạng thái ứng dụng. Vì vậy, tôi đã tạo một quy trình được lưu trữ trông giống như sau:

ALTER PROCEDURE [dbo].[UpdateApplicationState] 
(
    @ApplicationID INT, 
    @ApplicationStateID INT 
) 

AS 

BEGIN 

    UPDATE 
     [Application] 
    SET 
     ApplicationStateID = @ApplicationStateID 
    WHERE 
     ApplicationID = @ApplicationID; 

END 

Tôi đã tạo một hàm nhập có tên UpdateApplicationState. Ban đầu tôi đã đặt kiểu trả về là null, nhưng sau đó nó không được tạo trong ngữ cảnh. Vì vậy, tôi đã thay đổi kiểu trả về thành int. Bây giờ nó đã được tạo ra trong bối cảnh. Là nó khôn ngoan để trả lại một cái gì đó từ thủ tục lưu trữ của tôi?

Đây là phương pháp của tôi trong lớp ApplicationRepository tôi:

public void UpdateApplicationState(int applicationID, int applicationStateID) 
{ 
    var result = context.UpdateApplicationState(applicationID, applicationStateID); 
} 

Đây là mã gọi điện thoại của tôi để phương pháp này theo quan điểm của tôi:

applicationRepository.UpdateApplicationState(id, newApplicationStateID); 

Khi tôi chạy nó sau đó tôi nhận được lỗi sau:

The data reader returned by the store data provider does not have enough columns for the query requested.

Bất kỳ ý tưởng/tư vấn nào về những gì tôi có thể làm để làm việc này?

Cảm ơn

+0

Bất cứ ai biết nếu điều này được giải quyết trong EF5? –

Trả lời

16

Đó là vì bạn không thực sự trả lại bất kỳ thứ gì từ quy trình được lưu trữ của bạn. Thêm một dòng như dưới đây vào SP của bạn (SELECT @@ ROWCOUNT) và nó sẽ hoạt động đúng cách.

BEGIN  
    ... 

    SELECT @@ROWCOUNT 
END 

Trong khi giải pháp này sẽ giải quyết vấn đề của bạn và thực sự trả về số hàng bị ảnh hưởng bởi SP của bạn, tôi không rõ ràng về lý do tại sao đây là một vấn đề cho bạn:

I had initially set its return type to null, but then it wasn't created in the context.

Khi thực hiện một chức năng Nhập, bạn có thể chọn "Không" làm loại trả lại và nó sẽ tạo phương thức mới trên ObjectContext của bạn với kiểu trả về là int. Phương pháp này về cơ bản thực hiện một thủ tục được lưu trữ được định nghĩa trong nguồn dữ liệu; loại bỏ bất kỳ kết quả nào được trả về từ hàm; và trả về số hàng bị ảnh hưởng bởi việc thực hiện.

EDIT: Tại sao một chức năng không có giá trị trả lại được bỏ qua trong một kịch bản POCO:

Khoan vào ObjectContext T4 mẫu tập tin đến với ADO.NET C# POCO Entity Generator tiết lộ lý do tại sao bạn không thể nhìn thấy bạn Hàm trong lớp ObjectContext của bạn: Đơn giản là nó bị bỏ qua! Chúng chạy đến vòng lặp tiếp theo trong vòng lặp foreach tạo ra các hàm.

Giải pháp thay thế cho việc này là thay đổi mẫu T4 để thực sự tạo ra một phương thức cho các hàm không có kiểu trả về hoặc chỉ trả về một cái gì đó dựa trên giải pháp đầu tiên.

region.Begin("Function Imports"); 

foreach (EdmFunction edmFunction in container.FunctionImports) 
{ 
    var parameters = FunctionImportParameter.Create(edmFunction.Parameters, code, ef); 
    string paramList = String.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray()); 

    // Here is why a Function without return value is ignored: 
    if (edmFunction.ReturnParameter == null) 
    { 
     continue; 
    } 
    string returnTypeElement = code.Escape(ef.GetElementType(edmFunction.ReturnParameter.TypeUsage)); 
    ... 
+0

Khi tôi chọn không có thì chức năng nhập không nằm trong ngữ cảnh đối tượng của tôi. Nó không tồn tại. Tôi đã tìm kiếm nó. Khi tôi chọn nó để có kiểu trả về thì nó nằm trong ngữ cảnh đối tượng của tôi. Tôi đang sử dụng máy phát thực thể POCO. –

+0

Tôi không cần phải trả lại bất cứ điều gì đó là lý do tại sao tôi muốn đặt kiểu trả về là không, nhưng khi tôi làm theo cách này thì nó không tồn tại trong ngữ cảnh đối tượng của tôi. –

+0

Có, bạn đúng, trong một kịch bản POCO, nó bị bỏ qua và tôi chỉnh sửa câu trả lời của mình để cho biết lý do cho hành vi này. Tôi nghĩ rằng bạn đang sử dụng EntityObjects vì nó không phải là một vấn đề ở đó. –

20

Để POCO hoạt động với chức năng nhập trở về null, bạn có thể tùy chỉnh tệp .Context.tt như thế này.

Tìm "Nhập khẩu chức năng" có tên khu vực (phần bắt đầu bằng vùng.Bắt đầu ("Nhập khẩu chức năng"); và kết thúc bằng region.End();) trong tệp .Context.tt và thay thế toàn bộ phần đó bằng các mục sau:

region.Begin("Function Imports"); 

     foreach (EdmFunction edmFunction in container.FunctionImports) 
     { 
      var parameters = FunctionImportParameter.Create(edmFunction.Parameters, code, ef); 
      string paramList = String.Join(", ", parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray()); 
      var isReturnTypeVoid = edmFunction.ReturnParameter == null; 
      string returnTypeElement = String.Empty; 
      if (!isReturnTypeVoid) 
       returnTypeElement = code.Escape(ef.GetElementType(edmFunction.ReturnParameter.TypeUsage)); 

#> 
<# if (isReturnTypeVoid) { #> 
    <#=Accessibility.ForMethod(edmFunction)#> void <#=code.Escape(edmFunction)#>(<#=paramList#>)  
<# } else { #> 
    <#=Accessibility.ForMethod(edmFunction)#> ObjectResult<<#=returnTypeElement#>> <#=code.Escape(edmFunction)#>(<#=paramList#>)  
<# } #> 
    { 
<# 
      foreach (var parameter in parameters) 
      { 
       if (!parameter.NeedsLocalVariable) 
       { 
        continue; 
       } 
#> 

     ObjectParameter <#=parameter.LocalVariableName#>; 

     if (<#=parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null"#>) 
     { 
      <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", <#=parameter.FunctionParameterName#>); 
     } 
     else 
     { 
      <#=parameter.LocalVariableName#> = new ObjectParameter("<#=parameter.EsqlParameterName#>", typeof(<#=parameter.RawClrTypeName#>)); 
     } 
<# 
      } 
#> 
<# if (isReturnTypeVoid) { #> 
     base.ExecuteFunction("<#=edmFunction.Name#>"<#=code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>); 
<# } else { #> 
     return base.ExecuteFunction<<#=returnTypeElement#>>("<#=edmFunction.Name#>"<#=code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()))#>); 
<# } #> 

    } 
<# 
     } 

     region.End(); 

Điều tôi đang làm ở đây thay vì bỏ qua tất cả các hàm nhập trả về null, Tôi đang tạo một phương thức trả về null. Tôi hy vọng điều này là hữu ích.

+1

+1 để thực sự cung cấp giải pháp – bernhof

+0

+1 để thực sự cung cấp giải pháp –

Các vấn đề liên quan