Задача простая, выполнить хранимую процедуру с параметрами и получить результат.
В WCF хранимую процедуру реализую как в примере из книги http://my.safaribooksonline.com/book/programming/microsoft-dotnet/9781849685924/1dot-building-odata-services/id286697916#X2ludGVybmFsX0h0bWxWaWV3P3htbGlkPTk3ODE4NDk2ODU5MjQlMkZpZDI4NjY5NzkxNiZxdWVyeT0=
Проверяю решение в браузере вызовом своей SP с параметрами - работает.
Перехожу в клиентское приложение, пытаюсь вызвать ХП следующим образом:
Код | string uri = string.Format("http://localhost:4637/MainDataService.svc/uspGetOrdersByCustomer?customerId={0}", this.tbxUspGetOrdersByCustomer.Text); IEnumerable<MainDataServiceReference.uspGetOrdersByCustomer_Result> ordersList = context.Execute<MainDataServiceReference.uspGetOrdersByCustomer_Result>(new Uri(uri)); this.dgOrdersByCustomer.ItemsSource = ordersList;
|
Попутно проверяю получение List<T>:
Код | IEnumerable<String> stringList = context.Execute<String>(new Uri("http://localhost:4637/MainDataService.svc/GetStringList")); this.dgStringList.ItemsSource = stringList;
|
В OData 5.0.0 и OData 5.3.0 ошибки разные.
OData 5.0.0 WCF Data Service Server (Microsoft.Data.Services) 5.0.0 WCF Data Service Client (Microsoft.Data.Services.Client) 5.0.0 ODataLib (Microsoft.Data.OData) 5.0.0 EdmLib (Microsoft.Data.Edm) 5.0.0 System.Spatial 5.0.0
GetStringList: В строковом значении обнаружен XML-узел типа "Element". Элемент со строковым значением может содержать только узлы Text, CDATA, SignificantWhitespace, Whitespace и Comment.
uspGetOrdersByCustomer: Свойство "element" не существует в типе "WpfApplication.MainDataServiceReference.uspGetOrdersByCustomer_Result". Используйте только имена свойств, определенные в типе.
OData 5.3.0 WCF Data Service Server (Microsoft.Data.Services) 5.3.0 WCF Data Service Client (Microsoft.Data.Services.Client) 5.3.0 ODataLib (Microsoft.Data.OData) 5.3.0 EdmLib (Microsoft.Data.Edm) 5.3.0 System.Spatial 5.3.0
GetStringList: Невозможна материализация коллекции типов-примитивов или сложных типов без типа "Edm.String", который коллекцией.
uspGetOrdersByCustomer: Невозможна материализация коллекции типов-примитивов или сложных типов без типа "WpfApplication.MainDataServiceReference.uspGetOrdersByCustomer_Result", который коллекцией.
Data Services:
Код | public class TestDataService : DataService<EntityLib.MyEntities> { public static void InitializeService(DataServiceConfiguration config) { config.SetEntitySetAccessRule("*", EntitySetRights.All); config.SetServiceOperationAccessRule("*", ServiceOperationRights.All); config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3; }
[WebGet] public int GetInt() { return 1; }
[WebGet] public List<String> GetStringList() { List<String> myList = new List<String>(); myList.Add("First string"); myList.Add("Second string"); myList.Add("Third string");
return myList; }
[WebGet] public IQueryable<EntityLib.Order> GetOrderById(int orderId) { var res = this.CurrentDataSource.Order.Where(o => o.OrderID == orderId); return res; }
[WebGet] public IQueryable<EntityLib.uspGetOrdersByCustomer_Result> uspGetOrdersByCustomer(int customerId) { var res = CurrentDataSource.uspGetOrdersByCustomer(customerId).AsQueryable(); return res; } }
|
Client side:
Код | public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); context = new DataServiceContext(new Uri("http://localhost:4637/MainDataService.svc/")); }
DataServiceContext context;
private void btnGetInt_Click(object sender, RoutedEventArgs e) { IEnumerable<int> varInt = context.Execute<int>(new Uri("http://localhost:4637/MainDataService.svc/GetInt")); this.tbckGetInt.Text = varInt.LastOrDefault().ToString(); }
private void btnGetStringList_Click(object sender, RoutedEventArgs e) { IEnumerable<String> stringList = context.Execute<String>(new Uri("http://localhost:4637/MainDataService.svc/GetStringList")); this.dgStringList.ItemsSource = stringList; }
private void btnGetOrderById_Click(object sender, RoutedEventArgs e) { string uri = string.Format("http://localhost:4637/MainDataService.svc/GetOrderById?orderId={0}", this.tbxGetOrderById.Text); IEnumerable<MainDataServiceReference.Order> orderById = context.Execute<MainDataServiceReference.Order>(new Uri(uri)); this.dgOrderById.ItemsSource = orderById; }
private void btnUspGetOrdersByCustomer_Click(object sender, RoutedEventArgs e) { string uri = string.Format("http://localhost:4637/MainDataService.svc/uspGetOrdersByCustomer?customerId={0}", this.tbxUspGetOrdersByCustomer.Text); IEnumerable<MainDataServiceReference.uspGetOrdersByCustomer_Result> ordersList = context.Execute<MainDataServiceReference.uspGetOrdersByCustomer_Result>(new Uri(uri)); this.dgOrdersByCustomer.ItemsSource = ordersList; } }
|
Stored Procedure:
Код | CREATE PROCEDURE [dbo].[uspGetOrdersByCustomer](@customerId INT) AS BEGIN SET NOCOUNT ON;
SELECT OrderID, CustomerID, OrderDate FROM dbo.[Order] WHERE (CustomerID = @customerId) END
|
Метод GetOrderById работает, но он в отличии от моей хранимой процедуры возвращает не ComplexType, а EntityType.
Баг описан на http://connect.microsoft.com/VisualStudio/feedback/details/767210/wcf-service-opertation-unable-to-return-collection-of-type-enumerbale-string
Какие варианты можно применить в обход данной проблемы?
Проект: http://sdrv.ms/14Mcf2E |