Files to look at:
- Customer.cs (VB: Customer.vb)
- EndPointHelper.cs (VB: EndPointHelper.vb)
- Program.cs (VB: Program.vb)
- Service1.svc.cs (VB: Service1.svc.vb)
Scenario
In this example, we will create a WCF IDataStore service that will be used by our client (Console Application) as a data layer. Instead of a direct connection to the database, our client will connect to a remote service and configure the WCF end point programmatically. This is usually helpful when:
- WCF specific customizations are required to provide custom bindings, endpoints, behavior, e.g. for a secured connection;
- Your WCF service is not hosted in IIS and thus no .svc files are used (e.g., when the WCF Class Library project is used).
Steps to implement
1. Create a remote data service and client as described in the How to connect to a remote data service instead of using a direct database connection example.
2. Create an EndPointHelper class which implements the GetDataStore static method as shown in the EndPointHelper.xx file. This method will be used to configure the WCF end point on the client.
The key is in manual creation and custom configuration of the DataStoreClient and CachedDataStoreClient objects (you can see their default configurations by checking the source code of the CreateWCFWebServiceStore and CreateWCFTcpServiceStore methods of the DevExpress.Xpo.XpoDefault class).
3. Use the GetDataStore static method in the Main method as shown in the Program.xx file to configure end point and create a IDataStore.
Important notes
1. Take special note that binding customizations must be done both in client and service programs.
2. In XAF applications it is necessary to create a class that implements the IXpoDataStoreProvider interface and return the configured IDataStore. For additional information please refer to the How to use a custom ObjectSpaceProvider in XAF example that illustrates implementation of the IXpoDataStoreProvider interface.
Troubleshooting
- If WCF throws the "Entity is too large" error, you can apply a standard solution from StackOverFlow: http://stackoverflow.com/questions/10122957/
- If WCF throws the "The maximum string content length quota (8192) has been exceeded while reading XML data. " error, you can extend bindings in the following manner:
XML<bindings>
<basicHttpBinding>
<binding name="ServicesBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" transferMode="Streamed" >
<readerQuotas maxDepth="2147483647"
maxArrayLength="2147483647"
maxStringContentLength="2147483647"/>
</binding>
</basicHttpBinding>
</bindings>
See The maximum string content length quota (8192) has been exceeded while reading XML data
See also:
Endpoints: Addresses, Bindings, and Contracts
How to connect to a remote data service from a Silverlight application
How to implement a distributed object layer service working via WCF
How to create a data caching service that helps improve performance in distributed applications
How to connect to a remote data service instead of using a direct database connection
Extended IDataStore WCF-Service for tracking user access rights on the server after passing logon credentials from a client app
The GlobalDataClientChannelCreated or ClientChannelCreated events of the DevExpress.Xpo.DB > DataStoreClient class.
Does this example address your development requirements/objectives?
(you will be redirected to DevExpress.com to submit your response)
Example Code
C#using DevExpress.Xpo;
namespace E5137 {
public class Customer : XPObject {
public Customer(Session session) : base(session) { }
string _CompanyName;
public string CompanyName {
get { return _CompanyName; }
set { SetPropertyValue("CompanyName", ref _CompanyName, value); }
}
string _CompanyAddress;
public string CompanyAddress {
get { return _CompanyAddress; }
set { SetPropertyValue("CompanyAddress", ref _CompanyAddress, value); }
}
string _ContactName;
public string ContactName {
get { return _ContactName; }
set { SetPropertyValue("ContactName", ref _ContactName, value); }
}
string _Country;
public string Country {
get { return _Country; }
set { SetPropertyValue("Country", ref _Country, value); }
}
string _Phone;
public string Phone {
get { return _Phone; }
set { SetPropertyValue("Phone", ref _Phone, value); }
}
}
}
C#using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using DevExpress.Xpo.DB;
namespace E5137 {
public class EndPointHelper {
public static IDataStore GetDataStore(string connectionString) {
EndpointAddress address = new EndpointAddress(connectionString);
BasicHttpBinding binding = new BasicHttpBinding();
binding.MaxReceivedMessageSize = Int32.MaxValue;
binding.ReaderQuotas.MaxArrayLength = Int32.MaxValue;
binding.ReaderQuotas.MaxDepth = Int32.MaxValue;
binding.ReaderQuotas.MaxBytesPerRead = Int32.MaxValue;
binding.ReaderQuotas.MaxStringContentLength = Int32.MaxValue;
try {
IDataStore store = new DataStoreClient(binding, address);
store.AutoCreateOption.ToString();
return store;
}
catch(Exception e) {
throw new DevExpress.Xpo.DB.Exceptions.UnableToOpenDatabaseException(connectionString, e);
}
}
}
}
C#using System;
using System.Collections.Generic;
using System.Linq;
using DevExpress.Data.Filtering;
using DevExpress.Xpo;
namespace E5137 {
class Program {
static void Main() {
XpoDefault.DataLayer = new SimpleDataLayer(EndPointHelper.GetDataStore("http://localhost:55777/Service1.svc"));
XpoDefault.Session = null;
using(UnitOfWork uow = new UnitOfWork()) {
if(uow.FindObject(typeof(Customer), new BinaryOperator("ContactName", "Alex Smith", BinaryOperatorType.Equal)) == null) {
Customer custAlex = new Customer(uow) { ContactName = "Alex Smith", CompanyName = "DevExpress" };
custAlex.Save();
Customer Tom = new Customer(uow) { ContactName = "Tom Jensen", CompanyName = "ExpressIT" };
Tom.Save();
uow.CommitChanges();
}
using(XPCollection<Customer> customers = new XPCollection<Customer>(uow)) {
foreach(Customer customer in customers) {
Console.WriteLine("Company Name = {0}; ContactName = {1}", customer.CompanyName, customer.ContactName);
}
}
}
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
}
C#using DevExpress.Xpo;
using DevExpress.Xpo.DB;
namespace WcfService1 {
public class Service1 : DataStoreService {
public static IDataStore DataStore;
static Service1() {
string connectionString = MSSqlConnectionProvider.GetConnectionString("localhost", "ServiceDB");
DataStore = XpoDefault.GetConnectionProvider(connectionString, AutoCreateOption.DatabaseAndSchema);
}
public Service1()
: base(DataStore) {
}
}
}