Proper way to update a dictionary that is constantly being updated/read? - c#

I have a function that returns a Dictionary<uint, SomeClass> this function is called every second updating data to my list.
Right now, used like this to update my property:
MyData = Api.GetData();
And my property as:
public static Dictionary<uint, SomeClass> MyData { get; private set; }
Is that method fine to update my Dictionary or how should it be done?
I mean, the Dictionary is constantly being replaced as it is right now, right? So if I am using or updating any entry of that Dictionary say:
MyData[SomeValidKey].SomeProperty
My reference would become null or invalid? Or it would simple use a copy of it? Or this is something that would only have a chance to ever happen depending on how fast MyData is queried and the such?
What would be an optimal way to update my Dictionary, while allowing other parts of my application to freely access and use it?
The dictionary is mainly read only and/or call functions of a given item in the Dictionary that is part SomeClass.
UPDATE:
Since MyData = Api.GetData(); means the list is actually replaced? If so if an entry that previously existed no longer exist but any of my functions still had it in use, it would cause exceptions? If an item that was previously used is updated I would not have the updated data as my reference is dead?
So the way I am updating my Dictionary is clearly wrong?

If you're updating your Dictionary in a separate thread then you should use proper locking mechanism to ensure that you're reading the current value. Use lock for both read/write. Also there is a ConcurrentDictionary class in .NET 4 (or above) which is designed for concurrent operations.
But if you're using your dictionary in a single thread then you shouldn't worry about locking at all. Here is an example to demonstrate what happens when you change the reference to another someClass instance:
private class SomeClass
{
public string Name { get; set; }
}
...
Dictionary<uint, SomeClass> dic = new Dictionary<uint, SomeClass>
{
{ 1u, new SomeClass { Name = "1"}},
{ 2u, new SomeClass { Name = "2"}}
};
var sc1 = dic[1]; // sc1 refers to old instance of SomeClass
dic[1] = new SomeClass { Name = "new" }; // now we change the reference here
string oldName = sc1.Name; // oldName is still "1", because sc1 points to the old instance

Your question is different to your example. Your example states you are replacing your dictionary when you call your API. Your question corresponds to updating.
If you were to update your dictionary, then you can either assign the return of your Api call to a temporary dictionary, then transfer/add/delete values in MyData or pass MyData to your Api function and handle that functionality there. This would keep your references in tact if accessed from other parts of your application.
If this isn't possible, then you cannot guarantee that there aren't to be errors from other parts of your code when you replace your MyData object with your Api call. The easiest solution here would that you do not cache your MyData entry value but instead cache its key. Other parts of your application can then check if their cached key is valid and take appropriate action.

Related

How to copy object to keep references in C#

I recieve a JSON file from database in the c# client. Then I deserialize this JSON to an object of a class. Now when updated JSON arrives from database afterwards, what I want is to somehow replace every data of the old object with a new one. I need this because rest of code has many references to the old object and its properties, so simply assigning new object to old one would not work as all references would be lost. Is the only solution here performing a deep copy of the object? If so what is a best way to do this? Honestly I never needed anything like that for many years, I am quite surprised that this issue arise now but the reason is probably that I recieve dataj from database in JSON and have to someho deserialize it into new object.
The only solution I tried is manual copying of the fields betwee new and old object but its a pain to keep it updated whenever I change the class structure which I do a lot
SUGGESTION: Create a wrapper class with a property for the actual data. Pass a reference to your wrapper; read or update the data at will. The "reference" is unchanged; everybody will automatically "see" any data updates.
public class MyWrapper
{
public MyDataClass MyData { get; set; }
}
public class SomeClass
{
public void SomeMethod ()
{
// Instantiate your data
var wrapper = new MyWrapper();
wrapper.MyData = ReadFromDbAndDeserialize();
// And pass it to other client(s)
SomeOtherMethod(wrapper);
}
}
You could use Automapper to create deep copies automatically. You would need to set up some mappings manually though but it's less painful anyway.

Create a property accessed using a key rather than a method with a passed-in variable

I am creating a class (let's call it listClass) that provides a number of lists that get pulled from the database and cached for future use. One of these is to return a list of Regions for a given Country. I currently have it built as a method:
public static List<string> Regions(string country)
{
List<string> regions;
string cacheKey = "CachedRegions_" + country;
// try to get regions from cache
if (regions == null)
{
// load regions from database
// cache regions
}
return regions;
}
It is currently accessed thusly:
List<string> myRegions = listClass.Regions(myCountry);
However, as what I am accessing is much closer to a property than a method (and every other list in the class is a property), I feel it would be more appropriate to be able to access it like so:
List<string> myRegions = listClass.Regions[myCountry];
Note that I want to be able to cache the Regions for each Country separately (so I'm not caching/loading every region in the world each time I touch the property). Is there a way to create Regions as a property (that can be accessed via a key) rather than as a method?
Well, it's possible but it would require you to make Regions a property, and change the type of Regions to a structure that can be indexed by a string and returns a List<string>. Similar to a Dictionary<string, List<string>>, but with the additional logic in that type to load the data from a data source.
Rather than going through all of that, my opinion is it would be simpler just to change the name of the method to
public static List<string> GetRegions(string country)
That way it "feels" less like a property and you're out of the dilemma you're in. If you have other technical reasons for wanting to access it like an indexer then that may change things.
I want to be able to cache the Regions for each Country separately
Sure. You can still add caching in the method if you want. Or add it to this new class that you would create.

object passed to method by reference not maintaining values from DBContext

Basically, I'm passing a model object to a method and in that method, assigning the proper object from the database. Since this is a reference, I assumed it would persist throughout the rest of the method in which it it was called/passed. I know this has something to do with the proxy of entity framework but can't figure out how to fix it. Here is a fragment of the code:
[HttpPost]
public ActionResult Create(NewFormViewModel nfvm)
{
db = new dbconnection(connStr);
Track track= new Track();
Track parentTrack = new Track();
this.Create_SetTrack(nfvm, track, parentTrack);
...
and then in Create_SetTrack:
private void Create_SetTrack(NewFormViewModel nfvm, Track track, Track parentTrack)
{
track = db.Tracks.FirstOrDefault();
parentTrack = db.Tracks.Where(i=>i.ParentID==track.ID).FirstOrDefault();
}
The track loads in Create_SetTrack but then, after the code after the '...' continues in Create, track is back to it's null values.
Note that a method parameter is a new variable. So you assign track (the variable) to track (the parameter). In the method body, the parameter is overwritten by a new reference, but the original track (the variable) has nothing to do with that.
You are probably confused by the fact that changes you make to the same reference object will be visible outside the method body. If you'd only set a property of a new Track() object, you'd see this value after the Create_SetTrack call.
So I would make a method that returns the tracks, so you can assign then to the original variables. If this is an internal method, you could return a Tuple (using Tuples in API methods is discouraged, because the ItemX properties are too nondescript).
As an alternative, you could assign the tracks to another object (the view model?) that is not overwritten in the method body.
I'd prefer the first alternative though. I don't like methods that create side-effects.
That won't work unless you use a ref parameter. Otherwise, the track parameter reference will only exist in the scope of the method
private void Create_SetTrack(NewFormViewModel nfvm, ref Track track)
{
track = db.Tracks.FirstOrDefault();
}
I would advise against this, though, since it makes the code more complicated that it needs to be. A better solution is to simply return a value from the method and assign that to your variable:
private Track Create_SetTrack(NewFormViewModel nfvm)
{
return db.Tracks.FirstOrDefault();
}
[HttpPost]
public ActionResult Create(NewFormViewModel nfvm)
{
db = new dbconnection(connStr);
Track track= Create_SetTrack(nfvm);
....

Reference to cache object

I'm using .NET C# for a project.
I have a list of products which I want to cache as they're used company wide. If the products drop out of cache I already know how to lock the cache and rebuild it ok as per the patterns on various authority/blog sites.
In my pages/user controls etc, I might grab a reference to the cache, like this:
var myCacheInstance = cachedProducts
However, I might also want to do something like this:
myCacheInstance.Add(new product(...));
Which will also update the cache as it's the same object.
I have 2 queries.
If I have a reference to the cached object is it guaranteed to remain in cache for the lifetime of my variable?
In the scanario outlined above, how do I go about ensuring integrity? I'm only planning on adding in this instance, but suppose, I was updating and deleting objects as well?
1) If I have a reference to the cached object is it guaranteed to
remain in cache for the lifetime of my variable?
If I right interpret this question: responce is no.
cache.Add("key", new object()); // ADD KEY
var obj = cache["key"]; // GET REFERENCE TO CACHED OBJECT
cache.Remove("key"); // REMOVE OBJECT FROM CACHE
obj.DoSomething(..); //PERFECTLY VALID, STILL WORK ..
2) In the scanario outlined above, how do I go about ensuring
integrity? I'm only planning on adding in this instance, but suppose,
I was updating and deleting objects as well?
Can add bool property like, for example:
public bool IsValid
{
get; private set;
}
when object removed this property is set from the class to false. Just example, iff it really fits your need can tell us only you.
Do not pass around a reference to your cache!
Use an object for your cache and if a clients wants to have the cached items return a new list of your cached items, or a readonly collection.
If you want to add items to the cache, use a method on the cache object and in that method lock the cache and add the item. Same with remove.
question 1: If you pass around references you can not guarantee anything.
question 2: Use an object to cache all your items as I described above.
public class Cache
{
private List<Item> cachedItems = new List<Item>();
public void Add(Item item)
{
lock(cachedItems)
{
cachedItems.Add(item);
}
}
}
hello in order to ensure integrity, you must add key
Cache.Add("YourKey", yourValue)
here you can find helper for all operations
http://johnnycoder.com/blog/2008/12/10/c-cache-helper-class/
For duration or timeout you have this format, where you specify absoluteExpiration
public Object Add (string key, Object value, CacheDependency dependencies,
DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority
priority, CacheItemRemovedCallback onRemoveCallback)

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.

Categories