I'm currently working on a web service implementation to a combined web/desktop application (ie. access from different sources).
Now there are two questions I can't really find an answer to:
How would I access the database in the right way (static class? singleton? DI?)? I didn't find any information on using a Web Service in a DI container to help with the database access.
What about writing access? Is this the right way to offer a posibility of writing to the database? Of course, the requests would be protected with a userID and a key.
Note: this is NOT wcf, but the normal web service (ie. asmx file extension).
There are many "right" ways of accessing a database from a web service. Personally, I often use ADO.NET inside a static class (or, more accurately, a class with a bunch of static methods) that generally returns a DataTable (wrapped in a DataSet, which can be serialized and thus easily returned from a web service). You could also use an ORM (like NHibernate), although these invariably have a larger overhead than ADO.NET and thus are a potential source of load problems on your server.
There's no particular reason not to allow write access to your database from your web service. If your application design requires that the database be written to (obviously a pretty common requirement) then it's perfectly fine to do so from the web service.
Related
I don't know very much of WCF...
I want to do a clean job to serve entities on client side using DataContracts. Imagine two DataContracts "System" and "Building": "System" may have many "Buildings" and "Building" may have many "Systems". So, we have a many-to-many relationship between them.
In service contract model, "System" have a "Buildings" property that is a collection. "Building" also have a collection of "Systems".
The WCF uses DataSets for the underlying data access (with stored procedures for CRUD) and I have a table between SYSTEM and BUILDING representing the relationship.
So, how can I implement this scenario cleanly? I want the clients to be able to get a simple representation of "Buildings" in "System", for example, I could use:
system = GetSystem(id);
foreach (Building building in system.Buildings) {
// do whatever with each buildings...
}
Thank you!
I think this question is too broad to cover in full detail, but I can give you a few pointers to get you started.
Forget about WCF and build the Data Access Layer (DAL). This should be a library which contains code to query the database and return strongly typed objects. This library might contain a method called GetBuildings() which returns a list of Building objects. The library might work with DataSets (and other database specific types), but should not expose DataSets to external callers.
Now that you have a library which can be used to get data from the database, write the WCF service. Code in the service component should call into the DAL and turn that information into DataContract objects to be sent over the web service boundary. Don't try to represent all your data in the DataContract objects - you want your data packets to be relatively small, so don't include information that isn't required. Balance this with trying to make as few web service calls as possible. In designing your DataContract classes, consider what the client application will be doing with the data.
Write the Service Client component. This is code which makes calls to the WCF Service, and turns that information into Entity objects.
The final (and most rewarding step) is to write the client application logic. Now you have another set off issues to confront about how you will structure client code (I recommend using MVVM). The client application should call into the Service Client component, and use the data to meet the requirements of your application.
By following the above 4 steps, you should end up with:
A Data Access Layer that talks to the database.
A Service Layer, which knows nothing about the database but is able to fetch data from the Data Access Layer.
A Service Client layer, which knows nothing about databases but knows how to fetch data from the Service Layer.
Application code, which knows nothing about databases or web services, but calls into the Service Client layer to get data and presents the data to a User Interface.
Everyone will do this differently, but the main thing is to separate concerns by using a layered architecture.
What is the most effective way to sync two identically structured DataSets using a Web Service?
The design I use at the moment is simple without a Web Service. All data iscached on the Client, and it will only update data from the MySQL database if an update has been done, this is determined by a timestamp.
If possible I want to keep the same simple design, but add a Web Service in the middle, to allow easier access to the database over our limited VPN.
Best Regards, John
That's one heck of a question, but something I'm doing myself too. Easiest way I guess would be to add a "saved version" property. If it really is a simple design then you could just re-write only the DAL code to get things working for a web service. In fact, if the WSDL is done right, you may only need to make very minor adjustments (especially if the DB was previously designed using EF).
You say you want to sync two datasets simultaneously, but the question I guess is why? And which two? Do you have two web services, or are you wanting to sync data to both the local cache and the online web service (MSSQL db?) simultaneously?
I have windows forms app and server side services based on ADO.NET dataservice.
Is it a bad practice to create and initialize one static dataservice client in windows app and use it across the program? For example i can use it in all opened forms(which have bindings to service's datacontext's objects) to call SaveChanges() and not loose tracking.. Or creating a service client instance for every new form is better(because i think after some time with one static client there will be huge memory growth)? But when i create a new client for every form, i assume i create a new connection to the service every time..
May be im wrong and a bit confused about using services in client application. Please help me to understand the right way it works.
Actually the DataServiceContext class doesn't create a connection to the service. The OData protocol it uses is based on REST and as such it's stateless. So creation of the context alone doesn't even touch the service. Each operation (query, save changes) issues a separate and standalone request to the service. From the point of view of the service it's just number of unrelated requests.
As noted above it's usually a good idea to have a separate context for each "section" of your application. What is that exactly depends on your app. If you are not going to load/track huge number of entities (1000s at least) then one context might be fine. On the other hand several contexts give you the ability to "cancel" the update operations by simply droping the context and not calling SaveChanges, which might be handy in some applications.
I would say: It depends. ;) Well your problem is familiar to the decison you have to make, when using directly Entity Framework. So I recommend you to search for such articles and extract their point.
My own experience with EF tells me, that an application with several workflows should have a context for every workflow. Especially, when more than one workflow can be started at the same time and the user can switch between them.
If the application is simple it's proper approach to use only one context.
I'm currently involved in a very large supply chain management software system internal to where I'm employed. The system's UI is currently only implemented through ASP.NET, but we're in development of Windows Forms and Windows Mobile Compact interfaces as well. We have a pretty good setup in terms of separating the interface, business, and data access layers, so we have successfully shared across multiple platforms. However, we have some security concerns for when we distribute our client-based interfaces to the customer.
Several of our data access libraries are distributed with the executable. Simply opening the compiled assembly in Notepad gives full view to any queries within.
For example, let's say we have a class called "User" who implements the method "GetName" as:
select name from user where id = #id
The problem is that anyone keen enough to open the compiled assembly in Notepad can now see column and table names. Sure, they may not have access to these, but I'd still rather not expose the schema if I don't have to.
The above is just a simple example. Am I going about the thought process incorrectly, or is there a way to protect our queries? (I'd rather not resort to using stored procedures for everything.)
I've thought of forcing out data access layer to be remote and communicating from the business layer via web services so that all database related information is on our internal server that we can protect easier.
If you want to remove the sql from the src, then you are looking at another layer like web services. While that hides your sql, the services themselves must now be public. So while those who peek cannot see the db schema, they can still see the data layout.
What the web services allow for is an easier way to make schema changes since now you just have to make sure the data output is always the same. It also allows for you to move, rename, and/or perform other maintanence with the schema's dbs. Finally, it would better allow you to pool db connections local instead of over a network and have more processing run at the server.
I created a new solution with 3 projects:
My "Client" is a ASP.Net Web Application. This should display the information.
My Businesslayer should have all logic in it, it's designed as a normal class libery.
My "Server" is a WebService. This connect via Linq to the database and get the Information.
Now only my Server knows Linq and knows the Database (how it should be).
But how can I give Linq Objects throug the WebService to my Business and my WebApp Layer to use it There?
For my understand there must be a way, because I have e.g. a complete user object with all needed Information with Linq, so I don't must create a own one, must I?
Linq should be covered as well as database. Your business-logic layer and server should better have common core objects used in client-server calls: this also will provide you easy means to add some additional info that is not stored in DB (if needed in future).
I would recommend you to create internal classes corresponds to the linq entities and expose those objects through the web service instead. Then you create mapping methods within the service application to map between those types.