Synchronization within a multi-threaded operation contract - c#

Following operation contract constructs and return an de-serialized data structure called ObjectGraph. This is accomplished through
Step (a) retrieving an object id using logged in user. This ensures no two user get same object id.
Step (b) uses the object id (from Step a) to load the serialized object graph.
At this stage, both steps a and b are performed within a synchronized block using lock. This works as expected. However, I now want to split Step a and b separately due to performance concern as Step b takes comparatively longer than Step a and hence clients get queued-up easily.
Is it possible to split without loosing the synchronized access? If so, does someone know how ?
[ErrorBehavior(typeof(ErrorHandler))]
[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple, InstanceContextMode=InstanceContextMode.PerCall)]
public class ServiceImp : IService
{
private static object _lockOb = new object();
//ObjectGraph is a custom data structure.
public ObjectGraph GetObject(Guid IdUser)
{
lock(_lockOb) //This is to ensure that no two or more client execute below logic at any point in time.
{
//GetId method returns object id from database.
var id=GetId();
//LoadObjectGraphFromDatabase accept object id, read serialized data from database and finally returns a de-serialized ObjectGraph object.
var graph=LoadObjectGraphFromDatabase(id)
return graph;
}
}
}

Related

Can I safely wrap the current request in a static instance?

I'm working on a multi-tenant web application. At the beginning of each request, the web application will use either the URL or a cookie to determine the tenant ID of the current request. I want to make this available to my data layer so that it can automatically include the ID in SQL queries without having to explicitly pass it down through the layers for each query. However, I don't want my data layer to be dependent on System.Web or to only be usable by a web application.
So I've created an interface in the data layer ITenantIDProvider
public interface ITenantIDProvider
{
Guid GetTenantID();
}
And it could be implemented something like this:
public class TenantIDProvider : ITenantIDProvider
{
public Guid GetFacilityID()
{
return (Guid)HttpContext.Current.Items["TenantID"];
}
}
In reality it will be something more complex than just retrieving from Items but the key is that it will be using the current request. There is also a business logic layer in between but it just forwards the ID along so I left that code out for simplicity.
When the web application starts it passes a new instance of TenantIDProvider to the data layer which passes it into an instance of a custom EntityFramework IDbContextInterceptor:
//Static method in data layer called at application start up
public static void SetTenantIDProvider(ITenantIDProvider tenantIDProvider)
{
System.Data.Entity.Infrastructure.Interception.DbInterception.Add(new MyContextInterceptor(tenantIDProvider));
}
DbInterception.Add only gets called once at application startup so I believe it's storing the given interceptor in a static collection, which means my interceptor instance is common to all requests. However, since my tenantIDProvider is just wrapping access to the current request (and importantly, not setting any instance variables) I shouldn't need to worry about a race condition right? I've attempted to debug through two threads, freezing them at different times to test it and it seems to work as intended. I just feel a little uneasy about an instance of an object that is shared by all threads/requests trying to access request-specific data.

Passing a Data Object Between Dependent Factories

I'm currently using an IoC container, unity, for my program.
I have multiple chained factories. One calling the next to create an object it needs for populating a property. All the factories use the same raw data object in order to build their respective objects. The raw data object describes how to create all the various objects. Currently each factory has a Create method that takes in a couple parameters to state what location the object represents.
My problem is how/where do I pass in the raw data object to each factory in order for them to do their jobs?
Injecting the object into the Create() methods seems to be more procedural than object oriented. However if I inject the object into each factory's constructor then how would I resolve each factory correctly. Not to mention that these factories need to be able to work on different raw data objects. Maybe there is a better architecture over all?
Below represents the type of structure I have, minus passing the raw object anywhere.
class PhysicalObjectFactory
{
private readonly StructureAFactory _structureAFactory;
private readonly Parser _parser;
public PhysicalObjectFactory(StructureAFactory structureAFactory, Parser _parser)
{
_structureAFactory = structureAFactory;
this._parser = _parser;
}
public PhysicalObject CreatePhysicalObject()
{
RawDataObject rawDataObject = _parser.GetFromFile("foo.txt");
// do stuff
PhysicalObject physicalObject = new PhysicalObject();
physicalObject.StructureA = _structureAFactory.Create(num1, num2);
// do more stuff
return physicalObject;
}
}
class StructureAFactory
{
private readonly StructureBFactory _structureBFactory;
public StructureAFactory(StructureBFactory structureBFactory)
{
_structureBFactory = structureBFactory;
}
public StructureA Create(int a, int b)
{
// do stuff
StructureA structureA = new StructureA();
structureA.StructureB = _structureBFactory.Create(num76, num33);
// do more stuff
return structureA;
}
}
class StructureBFactory
{
public StructureBFactory(){}
public StructureB Create(int a, int b)
{
StructureB structureB = new StructureB();
// do stuff
return structureB;
}
}
My problem is how/where do I pass in the raw data object to each
factory in order for them to do their jobs?
In general you should pass in runtime data through methods and compile-time/design-time/configuration data through constructor injection.
Your services are composed at a different moment in time as when they are used. Those services can live for a long time and this means they can be used many times with different runtime values. If you make this distinction between runtime data and data that doesn't change throughout the lifetime of the service, your options become much clearer.
So the question is whether this raw data you're passing in is changing on each call or if its fixed. Perhaps it is partially fixed. In that case you should separate the the data; only pass the runtime data on through the Create methods. It seems obvious that since the factories are chained, the data they need to create that part of the object is passed on to them through their Create method.
Sometimes however, you've got some data that's in between. It is data that will change during the lifetime of the application, but do don't want to pass it on through method calls, because it's not up to the caller to determine what those values are. This is contextual information. A clear example of this is information about the logged in user that is executing the request. You don't want the caller (for instance your presentation layer) to pass that information on, since this is extra work, and a potential security risk if the presentation layer forgets to pass this information on, or accidentally passes on some invalid value.
In that case the most common solution is to inject a service that provides consumers with this information. In the case of the user information you would inject an IUserContext service that contains a UserName or UserId property, perhaps a IsInRole(string) method or something similar. The trick here is that not the user information is injected into a consumer, but a service that allows access to this information. In other words, the retrieval of the user information is deferred. This allows the composed object graph to stay independent of those contextual information. This makes it easier to compose and validate object graph.

Accessing properties of object stored in session

I must be misunderstanding something about session. I'm trying to store some information, so let me give the details.
Here's my "container" class that holds a list of business objects. This container is stored in session.
public class MySessionContainer {
private IList<SomeBusinessObjectType> _BusinessObjectList = new List<SomeBusinessObjectType>();
public IList<SomeBusinessObjectType> BusinessObjectList {
get { return _BusinessObjectList; }
set { _BusinessObjectList = value; }
}
}
I have a set of pages that form a wizard/multi-step process, and they all need to access the list of business objects in the container, which is in session.
The first page adds business objects to the list in session, so this sort of code is used to achieve that:
string key = GetKeyForCurrentUser();
MySessionContainer container = (MySessionContainer) Session[key];
SomeBusinessObjectType businessObject = /* Get object from view. */;
container.BusinessObjectList.Add(businessObject);
The generated key is always the same across all pages.
However, when the user gets to the second page, the container is in session as expected but the list of business objects is empty which is not what I expect. If the first page adds a business object, it should be there for the second and subsequent pages... right?
Is there something I am not understanding about session in ASP.net? Why is the container in session but not the list? Is the list not serialized with the container object when ASP.net writes/reads it from session?
You need to write it back to the session.
Take a look at the example under Session Variables:
// When retrieving an object from session state, cast it to
// the appropriate type.
ArrayList stockPicks = (ArrayList)Session["StockPicks"];
// Write the modified stock picks list back to session state.
Session["StockPicks"] = stockPicks;
ASP Session State Overview
Session object is not shared across different users so GetKeyForCurrentUser is useless. you can use some simple string for key. objects stored in Session must be serializable thus SomeBusinessObjectType must be serializable too.
Initalizers can act unexpectedly when serializing an object graph. Try using lazy loaded properties, if you don't want to initialize the collection out of the parent class:
public class MySessionContainer {
private IList<SomeBusinessObjectType> _BusinessObjectList;
public IList<SomeBusinessObjectType> BusinessObjectList {
get { return (_BusinessObjectList ??
(_BusinessObjectList = new List<SomeBusinessObjectType>()) ; }
set { _BusinessObjectList = value; }
}
}
This will allow deserialization to set your list and any getters will never get a null value for your collection.
Also, make sure every object in the graph can be serialized. See here for more information.
This question may also hold some relevance to yours.

Create property object on demand or in constructor?

What is the best way of initializing objects for properties without setters in C#?
For example I have property of type UserData and I can initialize it:
In constructor
In getter
private UserData _user;
public UserData User
{
get
{
return _user?? (_user= new UserData ());
}
}
Initialize field:
private UserData _user = new UserData()
I found few similiar threads:
Create an object in the constructor or at top of the class
C# member variable initialization; best practice?
But it is consideration between 1st and 3rd option - no one thinks about 2nd option - do you know way? From some time it is my preffered option to get objects, but I wonder if there are some cons that I don't know.
Could you tell me what is the best option and what problem could make use of 2nd option?
It all depends on what you want to do with it, so there is definite answer for that.
One difference between 1+3 and 2 is predictability.
With 1+3, you know exactly where your object is created and at which point during instantiation of your class. That can be desirable in some circumstances.
With 2, you depend on external influences (who accesses the property at which time) to initialize the field.
With the delayed creation in approach 2 (only create the object if needed), you could save some time when creating an object of the containing class.
If the UserData's creation takes a lot of time, like, when you have to query a database for it, you might want to delay its creation until really necessary. The object that contains the UserData object is constructed faster since it doesn't need to wait for the UserData object to be created. If the property isn't always accessed, you might even get to completely avoid creating a UserData instance.
If you're simply using plain data, initializing the backing field at its definition (if possible) is preferred:
// when you create constructor N+1, no worries about forgetting to set the value
private UserData _userData = new UserData();
public UserData User
{
get { return _userData; }
}
If you need initialization to be deferred, your best option is using Lazy<T>:
private Lazy<UserData> _userData = new Lazy<UserData>(() => new UserData());
public UserData User
{
get { return _userData.Value; }
}
The constructor for Lazy<T> contains overloads which can address your thread safety needs:
None: access from multiple threads is "undefined behavior"
PublicationOnly: the first thread to complete initialization "wins"
ExecutionAndPublication: locks ensure only one thread initializes the value
One issue with #2 is if the property could be accessed by multiple threads you could potentially create two copies of the UserData object. An additional consideration with #2 is if UserData is expensive to create you will be paying the cost of creating that object when the property is accessed rather than when the containing object is created. That may or may not be desirable depending on your use case.

.net remoting: Update already serialized objects

I got a MarshalByRefObject named "DefaultMeasurement", which contains a List of IPoint-objects.
public class DefaultMeasurement : MarshalByRefObject, IMeasurement
{
private List<IPoint> iPoints;
public this[int aIndex]
{
get { return iPoints[aIndex];}
}
}
[Serializable]
public class DefaultPoint : IPoint, ISerializable
{
public int Value {get;set;}
}
When first retrieving the DefaultMeasurement object from the server all the points get serialized and during all subsequent calls to DefaultMeasurement.Points I get the list that was correct upon startup of my client. But in the meantime the state of at least one object in that list might have changed and I don't get that current state, although in the server that state gets updated.
How do I force an update of that list?
further clarification:
- it will work once I do DefaultPoint : MarshalByRefObject, but that is not an option as it negatively affects performance
- by 'update' I mean changes to existing objects on the server, no adding / removing on the list itself
- I might have up to 80k DefaultPoint objects
Since you don't want the Point itself to be MarshalByRef (as that introduces a LOT of traffic if you have a substantial number of points), what I would recommend is that you have explicit methods that synchronize point values. After you've made a significant number of changes on the server, you call the SynchronizePoints() method, which includes new values for all of the points. Now the client-side proxy has an updated state. Better yet, remove the state from the object in the first place (since it's not really a direct reflection of server state) and instead use client-side objects that are instantiated as needed when gathering points from the server.
You would have to implement a callback that notifies the client of changes on the server.
The notify could pass id of the objects that have changed or the client could ask for a list of changed objects.

Categories