tags:

views:

270

answers:

5

We have an application where we wish to expose an large number of database entities and some business logic. Each entity will require the ability to Read , Add, and Update. at this point we do not expect to allow deletion.

the software we build is used in a wide range of business, so of which are multi tenanted operations Bureau services, also some of our clients use this approach to have separate databases for financial reasons.

We wish to be able to minimize the number of endpoints that need to be maintained. At the moment there are only 3 tables be exposed as WCF interfaces each with 6 attached methods. this is manageable but if operation has 50 databases that suddenly becomes 150 endpoints. worse if we have 50 tables exposed that becomes 2500 endpoints.

Does anyone have a suggestion on how we could design out system that we still have a simple entity model of Job.add (var1) or iList jobs = Job.GetSelected("sql type read").

without all these endpoints

A: 

It seems like you could pass the "identity" to every query and take that into account. This would mean that every record on your "Job" table would need to have a reference to the owner "identity" but that should not be much of a problem.

Just make sure that every query validates the "identity", and you should be OK.

Esteban Araya
One standard way to do this is with a session ID, typically passed in the HTTP cookie header.
Peter
A: 

If I understand your question correctly, I think you need unique endpoints but you can have a single service behavior that your end points reference.

Create a default endpoint:

<behaviors>
  <serviceBehaviors>
    <behavior name="MyService.DefaultBehavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>

Set your default binding:

<bindings>
  <wsHttpBinding>

    <binding name="DefaultBinding">
      <security mode="None">
        <transport clientCredentialType="None"/>
      </security>
    </binding>

  </wsHttpBinding>
</bindings>

Have all service reference point to the default behavior and binding:

<service behaviorConfiguration="MyService.DefaultBehavior"
           name="MyService.Customer">
    <endpoint address="" binding="wsHttpBinding" bindingConfiguration="DefaultBinding"
              contract="MyService.ICustomer">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>

Each time you add a service, its a simple config entry.

Coov
A: 

Providing Multi-Tenancy, Without A Bazillion End Points

One way is to go with a REST-style WCF service that can use username/passwords to distinguish which client you are working with, and thus be able to select internally which DB to connect to. WCF gives you the the UriTemplate which allows you to map part's of the URL to the param's in your web methods:

You can add other Uri Templates for more tasks as well, such as the following:

Who's Using My Service?

By requiring clients to supply a username and password, you can map that to specific DB. And by using the UriTemplate of /{tableName}/{operation}/{params...} you could then use code in your web service to execute the DB procedures given the table, operation, and params.

Wrapping It Up

Your web configuration wouldn't need to be altered much at all even. The following web article series is a great place to learn about REST-style web services, which I believe fits what you need: http://www.robbagby.com/rest/rest-in-wcf-blog-series-index/

arabian tiger
Putting the "verb" in the URL isn't considered RESTful. One of the basic REST preinciples is to use only GET, POST, PUT, and DELETE as your verbs. In this case GET would replace select, POST would replace insert, and PUT would replace update.
Peter
ah, good catch. i didn't realize i did that in my answer. so the url's could all be the same one, just using a different HTTP verb for the basic operations insert, update, delete, and select.
arabian tiger
I upated my answer, thanks again Peter!
arabian tiger
A: 

With Apache you can use a fairly simple set of URL rewriting rules to map an arbitrary set of DB table tables and their corresponding endpoints to a single endpoint with a parameter.

For example, to map $ROOT/table_name/column_name to $ROOT/index.php?tn=table_name&cn=column_name, you could add a rule like this to $ROOT/.htaccess:

RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/?$ index.php?tn=$1&cn=$2 [QSA,L]

Then you only need to maintain $ROOT/index.php (which of course can generate the appropriate HTTP status codes for nonexistent tables and/or columns).

Peter
+1  A: 

WCF Data Services allows you to expose your data in a RESTful manner using the Open Data protocal (OData). This was formally called ADO.Net data services and before that Astoria. Any IQueryable collection can be exposed. The way shown in most of the examples is to use the Entity Framework, however there are examples showing usage with NHibernate and other Data Access technologies. OData is a self describing API based on Atom-Pub with some custom extensions. With a minimal amount of code you can expose you're entire database in a well defined format. That's the easy part.

In order to implement multi-tenency, you can create query interceptors in the WCF Data Services application to implement that logic. The number of interceptors and the complexity of the code you write will depend upon your security model and requirements. Looking at something like T4 templates or CodeSmith to generate the interceptor methods based on your database schema may be a way to prevent lots of repetitive manual coding.

The link I provided has a lot of information and tutorials on WCF Data Services and would provide a good place to start to see if it would meet your needs. I have been looking at WCF Data Services for a similar problem (Multi-tenancy), and would love to hear how you evently implement your solution.