在運用Entity Framework調用存儲過程的時候,遇到"調用EF的存儲過程報"調用EF的存儲過程報“存儲區數據提供程序返回的數據讀取器所具有的列數對於所請求的查詢不夠”問題"的問題,存儲過程是用EF模型的函數導入(設置映射的存儲過程)。檢查過存儲過程,在Sql Management Studio運用是正常的。
存儲過程的部分代碼如下:
ALTER PROCEDURE [dbo].[GetNameByCustomerId] -- Add the parameters for the stored procedure here @CustomersId NVARCHAR(10), @CustomerName NVARCHAR(20) OUTPUT AS BEGIN from -- interfering with SELECT statements. SET NOCOUNT ON; ……… SELECT @CustomerName=c.CompanyName FROM Customers c WHERE c.CustomerID=@CustomersId END
調用存儲過程的EDMX的方法如下:
public void GetNameByCustomerId(string CustomerId, out string ContactName) { ContactName = string.Empty; var Pars = new System.Data.EntityClient.EntityParameter[] { new System.Data.EntityClient.EntityParameter{ ParameterName="CustomersId", DbType=System.Data.DbType.String,Value=CustomerId}, new System.Data.EntityClient.EntityParameter{ParameterName="CustomerName", DbType=System.Data.DbType.String, Direction=System.Data.ParameterDirection.Output} }; this.ExecuteNonQuery("GetNameByCustomerId", Pars); ContactName = Pars[1].Value.ToString(); }
函數與存儲過程應該都是沒有問題,在折騰了最后,發現我在函數導入(設置映射的存儲過程)時候,設置了存儲過程返回的集合。如圖:
添加函數導入的返回類型是指最后一個SELECT語句的字段類型(僅返回一個字段的情況);所以如果沒有使用SELECT語句返回則應該置返回類型為“無”;如果SELECT多個字段或者數據表行時必須將返回類型指定為“實體”(即DTO類型);如果是表就必須建一個對應的DTO;如果返回若干字段則必須為這些字段手工創建DTO類型。如果是返回DTO類型的則無需在分部類封裝方法了,直接使用導入的函數即可。
解決方法:
1). 在存儲過程return前,添加一條select語句,"select 1 as Result" ,使得存儲過程在return時有行列返回;
2). 不使用select 結果,則不需要返回類型,將添加函數導入時指定返回類型為“無”即可