Is there any way to share self tracking entities with client tier(from server tier which is WCF) like Data Contract.
I mean, do not include any assembly with STE to client, just get them from server e.g.
If "DAL" is the service reference, I want some like:
DAL.SomeEntity = new DAL.SomeEntity();
Self tracking entities must be shared with client in form of code or assembly. That is the main requirement to use them because they are not just a contract they also contain logic responsible for change tracking and this logic cannot be shared with the client in any other form.
Related
I am trying to build an AspNetCORE WebAPI that has various endpoints you can post to get information from a database.
The problem I am running into is trying to use dependency injection at the root layer to bind my DAL. Each request on the endpoint will carry metadata for the initial catalog. So the connection string has to be built from the request and then opened.
I have built a generic interface to work with my repos and then built a class that implements the interface, but in that implementation it still requires a data source to be newed up which at that point I don't have the DB to connect to.
So this forces me to new up a connection on every request.
If I abstract the DAL into a manager and then use DI to bind the managers, I still am missing the intial catalog detail
The SQL dbs all have the same schema, the only difference is the db name.
Is there a way to bind my DAL at the root while still being able to specify the connection string?
Trying to do this without EF, currently trying to figure out a way to handle this with Tortuga.Chain.
I'm going to be creating a service that needs to make a call to a hosted WCF service halfway around the world. This isn't that big of a deal since the number of transactions that will be made is relatively low. However, I need to pass in an instance of a class that will possibly be defined in the WCF to the necessary WCF function.
So my question is, will that instance of the class exist on my server? Or will I be contacting the host server every time I attempt to set a variable in the object?
EXAMPLE:`
public class Dog
{
public string noise;
public int numLegs;
}
public class doSomething
{
public string makeNoise(Dog x)
{
return x.noise;
}
}
`
All of those are defined in the WCF. So when I create an instance of class Dog locally, will that instance exist on my side or the server hosting the WCF service? If I'm setting 1000 instances of Dog, the latency will definitely build up. Whereas if I DON'T have to contact the server every time I make a change to my instance of Dog, then the only time I have to worry about latency is when I pass it into doSomething.makeNoise.
The host creates a new instance of the service class for each request, if you're using the default per-call instantiation method (which is the recommended way).
So either this is the IIS server which hosting your WCF service that creates an instance of your service class, or it is the ServiceHost instance that you've created inside your own self-hosting setup (a console app, a Windows service etc.).
The service class instance is used to handle your request - execute the appropriate method on the service class, send back any results - and then it's disposed again.
There's also the per-session mode in which case (assuming the binding you've chosen support sessions) your first call will create a service-class instance, and then your subsequent calls will go to the same, already created instance (until timeouts come into play etc.).
And there's also the singleton mode, where you have a single instance of the service class that handles all requests - this is however rather tricky to get right in terms of programming, and "challenged" in terms of scalability and performance
You will need to host your WCF service on a public available server (for example IIS). Successful hosting will provide you with a link for the svc file. Clicking on that will give you a link ending in singleWsdl. You need to copy that link. On your client side, the one that requires a reference to the WCF, you will need to Add Service Reference and pass that link. This will generate proxy code with Client objects that you can use to access your WCF ServiceOperation methods.
At a minimum you should have three projects. A website project to host the actual site. A WCF project to host your services. And finally a shared project, which should contain the classes you are concerned with (the models).
Both the website and wcf projects should reference the shared project, this way they both know how the models look.
The wcf project should return serialzed models as json objects, which I usually do by referencing Newtonsoft.Json.
Your website project should expect this json, and deserialize them, also using Newtonsoft.Json. This is why your class (model) should exist in the shared project, so you can use the same class on both sides of your service call.
I have a self hosted WCF service that I am using in a silverlight application. I am trying to store a list of user guids in an IDictionary object. Each time a user hits the service, it updates the users datetime so I can keep track of which users have active "sessions". The problem is, every time I am hitting the service, the list is empty. It appears to be dropping the values on each soap request?
Can you store information in a self hosted service that will be available across multiple service requests?
Thanks in advance!
It's on a per instance basis. I.e session-less by default.
Have a look at this
When a service contract sets the
System.ServiceModel.ServiceContractAttribute.SessionMode property to
System.ServiceModel.SessionMode.Required, that contract is saying that
all calls (that is, the underlying message exchanges that support the
calls) must be part of the same conversation.
If you need to store things in between requests you will need to create either a static dictionary with the appropriate locking to store these requests as they come in, or store this info in a database (or other external store) and check to see if it exists there in each method call. The reason for this is that the service class is instantiated on every client request.
Since you are already updating the users datetime when a user hits the service it would be better do a lookup to see if this is an active user or not by comparing to the datetime field. This has the advantage of being accurate on every call (the dictionary could get out of sync with the db if the service is restarted). Databases already have mechanisms in place to deal with concurrency, so rather than rolling your own locking solution around a singleton object you can push the complexity to the data store.
If the second solution is not fast enough (and you have profiled the app and determined it's the bottleneck), then the other option is to use some kind of cache solution in front of the db so that data can first be checked in memory before going to the db. This cache object would need to be static like the dictionary and has the same pitfalls around locking as any other multi-threaded application.
EDIT: If this hosted WCF service is being used as session storage for the users of the silverlight application and the data is not being stored in an external data store, then you better be sure that tracking if they are active is not mission critical. This data cannot be guaranteed to be correct as described.
Based on the accepted answer if your service faults and needs to be rebooted (since this is self hosted it is advised that you monitor the faulted event) you have to dispose of the service host and instantiate a new one. The only way the Guid data can be kept is if it is rebound to the service in between restarts (assuming the host app itself isn't restarted which is a different issue).
private Dictionary<Guid,string> _session;
Service service = new Service(_session);
_serviceHost = new ServiceHost(service, GetUriMethodInHostApp());
Better would be to store this externally and do a lookup as #marc_s suggests. Then this complexity goes away.
You need to change the InstanceContextMode. You can do so by adding the following compiler directive to your WCF class:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
This will run the WCF service as a singleton of sorts. See more on WCF Instance Context Mode
And then you should construct your service host with your singleton object. Here's code from a working example where I'm doing something similar:
private ServiceHost serviceHost;
if (serviceHost != null)
serviceHost.Close();
if (log.IsInfoEnabled)
log.Info("Starting WCF service host for endpoint: " + ConfiguredWCFEndpoint);
// Create our service instance, and add create a new service host from it
ServiceLayer.TagWCFService service = new ServiceLayer.TagWCFService(ApplicationName,
ApplicationDescription,
SiteId,
ConfiguredUpdateRateMilliseconds);
serviceHost = new ServiceHost(service, new Uri(ConfiguredWCFEndpoint));
// Open the ServiceHostBase to create listeners and start listening for messages.
serviceHost.Open();
As others have politely noted, this can have "consequences" if you're not familiar with how it works or if it's not a good fit for your particular application.
If you don't what to involve locking and thread-safe specific code, you can use a NoSQL database to store your session data, something like MongoDB or RavenDB
Like #marc_s, I think that using the Singleton mode is a risky thing, you have to be very careful in making your own thread-safe session mechanism.
My architecture is thus: UI project (MVC), connected to my Domain Service Layer (Business rules etc), connected to a Repo Layer.
When setting up view models i seem to be making many calls to the database 9via service layer) to set up a viewmodel (i.e. view) within the controller, is this the correct thing to do...
E.g. I have a client, they can become a Head Office (checkbox), if they become/ or are a HeadOffice they have the option to add many different clients. This particular view will contain: The client details, Available clients to add and current clients that are part of the head office...
To me it appears as if I should be checking everying within the Domain Service Layer and giving back to the controller what it can see i.e. If it is a HeadOffice is has x number of clients it can add???
I'm not entirely sure on the question, but here is my understanding of the issue...
1) A client record will contain certain information in all cases, and you can get back a client record in one call
2) IF a client record has IsHeadOffice == true, you might additionally choose to load an IEnumerable list of client records that "belong" to the "head office client"
I don't really see a problem in making two calls, one to the "get client" method and one to the "get clients for head office user" method.
You could façade these in your service layer and return the entire client, with all associated clients in one call if you wish.
If you try and tie your service up with your UI, you will write unnecessarily complicated methods to return "complete" sets of data. If you are calling 50 different methods from the UI, that might not be performant and you might want to aggregate it further down the stack.
I'll be more specific.
Lets say I have a contract defined for my WCF service. And I have two different WCF clients which reference to this service : "ClientA" and "ClientB".
Now , lets say I want to add an operation (method) to my service which only "ClientB" will use , Lets say I added this operation to the contract and "ClientB" updated its reference and we're all happy. Does clientA also need to update it's reference even though it is not using the new operation?
The client only needs to update his reference, if it's going to use the new Operation contract.
Check out this article: Versioning WCF Contracts
No, WCF web references are generated by the IDE very similarly to references to ASMX or other web services, which means that it breaks things down into a method inventory, such that the client calling code operates as though it were invoking a remote API. Therefore, if only new stuff that does not alter the expected existing functionality is added, then old clients do not need to update.