I have a wcf web service which i want to share information between calls (diferent clients calls) .
for example sharing a dictionary between client calls. the dictionary can be change through calls (add/remove item etc) but i cant efford it to be deleted or to be renew for each call (it should be like a static database) .
is there any way to implement this issue?
allready tried a few suggestions but nothing realy seems to work.
You basically need a singleton defined outside of your service class - you would need to handle the very likely possibility that multiple calls will be accessing / modifying the info at the same time so will need to lock the data maybe with a ReaderWriteLock or ReaderWriterLockSlim.
A nicer way of doing it, assuming you are using .net 4.0, would be to use MemoryCache, which contains built-in thread safety. If you are pre .net 4.0, there is a cache object in the System.Web namespace link - it was a bit of a pain having to add reference to system.web if you wanted to use it when writing windows apps so the MemoryCache implementation in .net 4.0 was a welcome addition.
Related
Our ticket system vendor provides an .NET API library and I've been trying to make use of this from a multi-threaded application. I'm running into all sorts of connection/stateful issues and I believe this is perhaps because it's not "thread-safe" (I'm still a novice with C# and threaded applications, so just my guess at the moment as some of the symptoms line up).
The API doesn't have a class that is instantiated, you just call the static methods TrebuchetApi.Api.Connect() and TrebuchetApi.Api.Login() from it's namespace (in fact all methods appear to be static).
So I maybe have one thread doing one thing, and another doing something else, and the underlying API is getting confused (static variables that should be set are null and such).
Is there any way of making each of my threads use a brand new 'instance' of the API, or is it simply unavoidable?
Update:
For clarity, after the suggestions for using AppDomains I found this article which provided the exact framework I needed:
http://www.superstarcoders.com/blogs/posts/executing-code-in-a-separate-application-domain-using-c-sharp.aspx
Using appdomains seems like the way to go.
See How do I prevent static variable sharing in the .NET runtime? or In .Net is the 'Staticness' of a public static variable limited to an AppDomain or the whole process? for similar questions people had.
The msdn guide can be found here http://msdn.microsoft.com/en-us/library/ms173138(v=vs.90).aspx
Just keep in mind that AppDomain is a .net concept, unmanaged resources can still be an issue.
Ok so I have built my WCF service and its functioning great! However, I am starting to implement it into our pre-existing piece of software now and I am instantly running into the question, do I only use the proxy generated code and get rid of the dll that I used initially? Or do I keep both, and make distinctions between the two very obvious?
What I mean by keeping distinctions is, having a ServerUser and a LocalUser property that represent the same user object. However, my LocalUser property would be filled via the dll that the app initally ran with, if the application service is unavailable.
My main reasoning for this thought pattern is that if I remove my dll, I have a single point of failure. If for some reason my ServiceHost is just not up and running, but the DB server is, I would want my users to still be able to do their job. The features that the new WCF implementation utilize are not dependant for employees to do their job. It is more of a convenience in what the WCF service provides. Also, building in this kind of logic to the Service would allow service modifications more readily available in a non IIS hosted environment.
Also, is there a way to build in logic on the service so that when I pull down the proxy code for the client that it just knows to access the DB manually if the ServiceHost is unavailable? If this was a possibility, I think about 90% of all my problems would disappear.
Thank you in advance!
From what you describe it sounds like keeping your existing DLL, i.e. direct access to the DB, would best suit your needs. Having a WCF service adds nothing if, when it fails, you'll just use the DLL anyway.
Ideally you would go with the WCF service completly and offer some kind of redundency to deal with any potenial service issues. Plus, using a service will mean you won't have to deal with any DLL upgrades/deployments.
But, from your question, it sounds like there would be some real issues to deal with should the service not be available, so just do with the DLL.
EDIT: Just read the last part of your question and I don't think that is possible. The proxy code for accessing services is generated when you add the reference to your project. The kind of "dynamic" information you're after would actually require a service.
EDIT: As a follow up to my comment below you could test this by creating a DLL and class, lets call it Class1. Then create a WCF service with a method that will return Class1. Create a client application and add a reference to the service. If you look at the proxy-generated code you should see (hopefully...I'm thinking of this as I type :)) that the method returns Class1, but when you compile it won't be able to find Class1. This is because Class1 does not have the DataContractAttribute which would auto-generate Class1 on the client. So, you have to distribute the shared DLL to the client. Now when the method returns and WCF tries to re-create Class1 it will use the local version in the shared DLL. Your other DLL, which will already be on the client, would use the same shared DLL.
Our applications use a lot of shared components. Some of them have no need for caching, for example, Windows Services which process unmailed emails. You'd never cache that result set...
Problem is, since our shared data layer has been modified to use SqlCacheDependency, our services which don't start SqlDependency fail on database calls where the data layer requests a SqlCacheDependency object.
Which leads to the question - is there a way for our data classes to test to see if the broker service is listening (ie: has SqlDependency.Start(connectionString) been called)?
The SqlDependency object itself has no Enabled or similar property. Is there any way short of forcing the calling app to tell the data layer that SqlCaching is in use for the data layer to determine the state?
Pretty much the answer is no. We ended up adding a config variable that if false or not present, causes the request to use SqlCacheDependency to be skipped.
SELECT * FROM sys.service_queues WHERE name LIKE 'SqlQueryNotificationService-%'
returns a 'SqlQueryNotificationService-[some guid]'
And if you look deep in the Non-public members of the SqlDependency _serverUserHash while debugging in the IDE, you'll find a collection that contains that same entry. If Microsoft would be so kind as to expose that, then yes.
In my case I have a class library which is used by some web applications. So I have no App.config. I also use the SqlCacheDependency in a static event. So I'm using a static boolean like:
if (!isCachingEnabled)
isCachingEnabled = SqlDependency.Start(builder.ProviderConnectionString);
So far is working but I'm open to suggestions when using Class Libraries.
First off, I wish context based storage was consistent across the framework!
With that said, I'm looking for an elegant solution to make these properties safe across ASP.NET, WCF and any other multithreaded .NET code. The properties are located in some low-level tracing helpers (these are exposed via methods if you're wondering why they're internal).
I'd rather not have a dependency on unneeded assemblies (like System.Web, etc). I don't want to require anyone using this code to configure anything. I just want it to work ;) That may be too tall of an order though...
Anyone have any tricks up their sleeves? (I've seen Spring's implementation)
internal static string CurrentInstance
{
get
{
return CallContext.LogicalGetData(currentInstanceSlotName) as string;
}
set
{
CallContext.LogicalSetData(currentInstanceSlotName, value);
}
}
internal static Stack<ActivityState> AmbientActivityId
{
get
{
Stack<ActivityState> stack = CallContext.LogicalGetData(ambientActivityStateSlotName) as Stack<ActivityState>;
if (stack == null)
{
stack = new Stack<ActivityState>();
CallContext.LogicalSetData(ambientActivityStateSlotName, stack);
}
return stack;
}
}
Update
By safe I do not mean synchronized. Background on the issue here
Here is a link to (at least part of) NHibernate's "context" implementation:
https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/Context/
It is not clear to me exactly where or how this comes into play in the context of NHibernate. That is, if I wanted to store some values in "the context" would I get "the context" from NHibernate and add my values? I don't use NHibernate, so I don't really know.
I suppose that you could look and determine for yourself if this kind of implementation would be useful to you. Apparently the idea would be to inject the desired implementation, depending on the type of application (ASP.NET, WCF, etc). That probably implies some configuration (maybe minimal if one were to use MEF to load "the" ICurrentSessionContext interface).
At any rate, I found this idea interesting when I found it some time ago while searching for information on CallContext.SetData/GetData/LogicalSetData/LogicalGetData, Thread.SetData/GetData, [ThreadStatic], etc.
Also, based on your use of CallContext.LogicalSetData rather than CallContext.SetData, I assume that you want to take advantage of the fact that information associated with the logical thread will be propagated to child threads as opposed to just wanting a "thread safe" place to store info. So, if you were to set (pr Push) the AmbientActivity in your app's startup and then not push any more activities, any subsequent threads would also be part of that same activity since data stored via LogicalSetData is inherited by child threads.
If you have learned anything in the meantime since you first asked this question I would be very interested in hearing about it. Even if you haven't, I would be interested in learning about what you are doing with the context.
At the moment, I am working on maintaining some context information for logging/tracing (similar to Trace.CorrelationManager.ActivityId and Trace.CorrelationManager.LogicalOpertionStack and log4net/NLog context support). I would like to save some context (current app, current app instance, current activity (maybe nested)) for use in an app or WCF service AND I want to propagate it "automatically" across WCF service boundaries. This is to allow logging statements logged in a central repository to be correlated by client/activity/etc. We would be able to query and correlate for all logging statements by a specific instance of a specific application. The logging statements could have been generated on the client or in one or more WCF services.
The WCF propagation of ActivityId is not necessarily sufficient for us because we want to propagate (or we think we do) more than just the ActivityId. Also, we want to propagate this information from Silverlight clients to WCF services and Trace.CorrelationManager is not available in Silverlight (at least not in 4.0, maybe something like it will be available in the future).
Currently I am prototyping the propagation of our "context" information using IClientMessageInspector and IDispatchMessageInspector. It looks like it will probably work ok for us.
Regarding a dependency on System.Web, the NHibernate implementation does have a "ReflectiveHttpContext" that uses reflection to access the HttpContext so there would not be a project dependency on System.Web. Obviously, System.Web would have to be available where the app is deployed if HttpContext is configured to be used.
I don't know that using CallContext is the right move here if the desire is simply to provide thread-safe access to your properties. If that is the case, the lock statement is all you need.
However, you have to make sure you are applying it correctly.
With CallContext, you are going to get thread-safe access because you are going to have separate instances of CallContext when calls come in on different threads (or different stores, rather). However, that's very different from making access to a resource thread-safe.
If you want to share the same value across multiple threads, then the lock statement is the way to go. Otherwise, if you want specific values on a per-thread/call basis, use the CallContext, or use the static GetData/SetData methods on the Thread class, or the ThreadStatic attribute (or any number of thread-based storage mechanisms).
I have two projects, the DLL project which has all my logic and data access stuff, and the ASP.NET project which does my forms etc.
I am a bit confused. I thought if I added the System.Web namespace reference to the DLL project I would be able to reference the Session state information of the ASP.NET page.
I could use each page to get the session info out and pass it to the DLL for the processing but would love to be able to process things directly from the DLL class(s).
Is this possible?
I have fiddled with the System.Web namespace and just seem able to get a reference to the Session variable.
Thanks all.
Jon
As long as the Assembly is loaded in the scope of the Session, it will have access.
Although this type of tight coupling isn't really recommended.
You should be able to use HttpContext.Current.Session
Edit
While yes I agree you should not tightly couple your Business Logic DAL or etc assemblies to ASP.Net session. There are plenty of valid cases for accessing HTTP Context outside of a web project.
Web Controls is probably one of the best examples, reusable HTTP modules, etc..
Now one option, if you want to have your DLL pull the stuff from Session, is to abstract out session. So you could define an interface like IStorage, that your library will know how to use. Then you can have a SessionStorage or MemoryStorage class and use IoC to inject the appropriate class into your library classes. This gives you the freedom to code it how you wanted it to be coded without tying your code to Session. Oh and one other benefit if done properly can be used to not tie your code to the session on the web either.
You can always use HttpContext.Current.Session in your DLL but this is considered as bad practice. A better approach would be to pass the values stored in the session dictionary to your DLL instead of it referencing the session. Another benefit you will gain is that the code in your DLL won't be coupled to the ASP.NET runtime meaning it will be easier to test.
As said by the others, you can always use HttpContext.Current.Session in your DLL, I assume it's your BAL, but you need to be really carefull. What if your DLL is later consumed by a windows service, or some other app that doesn't have an HTTPContext? Whenever I've done this it's always been in a property get method where I wrap the attempt to access HttpContext.Current.Session in a try catch block and if anything goes wrong I repull the needed data from the db.
Do not use HttpContext.Current.Session as your dll will not run always with the Web Application. It may run with any other application like Windows,Console itc.
It is better to use a Method which is actully accept a parameter, which will come form Session Value, if you are using ASP.Net Application, otherwise there will not be any dependency of the application. If your dll project already developed and you are trying to modify the exsiting business logic then no, dont modify your exsiting method, use an Overload method.