C# ConcurrentDictonary how to update value properties? - c#

I store this class
public class Customer
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public string CustID { get; set; }
}
In this dictionary :
public static ConcurrentDictonary<string, Customer> Customers = new ConcurrentDictonary<string, Customer>();
The key is a unique string for each customer.
I am trying to find the cleanest thread-safe way to update properties of the customer's stored in the dictionary.
Sorry if the code above has any syntax issues, typed it in from a smartphone.
Here is what I’m currently doing:
Customer oCustomers = new Customer();
Customers.tryGetValue(ID, out oCustomers);
Customer nCustomer = new Customer();
nCustomer = oCustomer;
nCustomer.Firstname = NewValue;
Customers.tryUpdate(ID, nCustomer, oCustomer);
This works but seems so hacked to me, any suggestions would be great.
This was closed as a duplicated question that asks how to modify the ConcurrentDictionary in a thred-safe way. I'm asking how to modify individual customers, not the dictionary.
I have not found an answer on stack overflow and have searched for some time. Will someone please re-open this question so I can’t get the help I came here for.

ConcurrentDictionary is a dictionary that is thread safe by default and all operations involving it are atomic by design.

ConcurrentDictionary is thread-safe. It just depends on what you expect from thread safety.
From MSDN
ConcurrentDictionary<TKey, TValue> is designed for multithreaded scenarios. You do not have to use locks in your code to add or remove items from the collection. However, it is always possible for one thread to retrieve a value, and another thread to immediately update the collection by giving the same key a new value.

The ConcurrentDictionary is thread-safe. That doesn't mean that its contents are.
The easiest way to ensure thread-safety is to make the objects immutable and replace them with a new one when you want to change the values. That's how immutable types in functional languages like F# work.
Your code though, doesn't do that. It's still modifying the stored object. When you type nCustomer = oCustomer you don't clone the object, you change the variable to point to the original oCustomer.
You can make the class immutable by using only readonly properties which are initialized by the constructor :
public class Customer
{
public string FirstName { get; }
public string LastName { get; }
public string CustID { get; }
public Customer(string firstName,string lastName,string custID)
{
CustID = custID;
FirstName=firstName;
LastName=lastName;
}
}
To update a customer, pull it from the dictionary, create a copy and call TryUpdate. Make sure to check for success. If TryUpdate fails it means some other thread modified the customer and you probably need to retry. Eg:
Customer old;
if (customers.TryGetValue(ID, out old))
{
var newCustomer = new Customer(newName,old.LastName,old.CustID);
if(!customers.TryUpdate(ID,newCustomer,old))
{
// Who moved my cheese ?
}
}
else
{
//No customer!
}
You'll have to decide what to do if the customer value has changed:
You can retry the update, thus overwriting any other updates.
You can try reloading the customer and make your update, assuming that whoever changed the customer changed one of the other fields.
You can stop trying and warn the user that the record has already changed

Related

C# Concurrent Dictionary Object Read/Update Thread Safety Question

In the code below I have a concurrent dictionary that i'm using for storing a single key/value pair where the value is a collection of strings.
I will be reading and updating the strings in this single key/value pair from different threads.
I'm aware that concurrent dictionaries are not entirely thread safe if one thread has changed a value before the other thread has perhaps finished reading it. But equally i'm not sure if string values really come into this topic or not, could someone please advise?
Its also worth mentioning that although I put this "GetRunTimeVariables" method into an interface for dependency injection, I actually cant use DI all the time for accessing this method due to the stages of app startup and OIDC events sign in/out where i need to access the dictionary values within classes that can't use dependency injection, so in essence I could be accessing this dictionary from nay means as necessary throughout the lifetime of the application.
Lastly i'm not really sure if there is any benefit in pushing this method into an interface, the other option is simply new up a reference to this class each time i need it, some thoughts on this would be appreciated.
public class RunTimeSettings : IRunTimeSettings
{
// Create a new static instance of the RunTimeSettingsDictionary that is used for storing settings that are used for quick
// access during the life time of the application. Various other classes/threads will read/update the parameters.
public static readonly ConcurrentDictionary<int, RunTimeVariables> RunTimeSettingsDictionary = new ConcurrentDictionary<int, RunTimeVariables>();
public object GetRunTimeVariables()
{
dynamic settings = new RunTimeVariables();
if (RunTimeSettingsDictionary.TryGetValue(1, out RunTimeVariables runTimeVariables))
{
settings.Sitename = runTimeVariables.SiteName;
settings.Street = runTimeVariables.Street;
settings.City = runTimeVariables.City;
settings.Country = runTimeVariables.Country;
settings.PostCode = runTimeVariables.PostCode;
settings.Latitude = runTimeVariables.Latitude;
settings.Longitude = runTimeVariables.Longitude;
}
return settings;
}
}
Class for string values:
public class RunTimeVariables
{
public bool InstalledLocationConfigured { get; set; }
public string SiteName { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string PostCode { get; set; }
public string Latitude { get; set; }
public string Longitude { get; set; }
}
The System.String type (the classical strings of C#) is immutable. No one can modify the "content" of a String. Anyone can make a property reference a different String.
But in truth the only problem you have here is that the various values could be de-synced. You have various properties that are correlated. If one thread is modifying the object while another thread is reading it, the reading thread could see some properties of the "old" version and some properties of the "new" version. This isn't a big problem if the object once written to the ConcurrentDictionary is not changed (is "immutable" at least as a business rule). Clearly a correct solution is to have RuntimeVariables be an immutable object (composed only of readonly fields that are initialized at instancing for example)

Update all Fields passed in object without using replace

I'm writing a wrapper around certain functions of mongodb to enforce certain buisiness policies (such as having a last modified date, a document version &c). These extra fields will not appear in the model and will be irrelevant and transparent to the person implementing against this library. This library will be generic.
Therefore using replaceOne is out of the question.
What I would like is some way of passing all fields in a person passed object to the Update builder - so I can use .Set/.Inc accordingly to add the other fields.
An example to demonstrate what I want is below:
public static async Task UpdatePerson(string name, Person person)
{
var client = new MongoClient("mongodb://localhost:27017");
IMongoDatabase db = client.GetDatabase("test");
IMongoCollection<Person> collection = db.GetCollection<Person>("people");
var query = Builders<Person>.Filter
.Eq("name", name);
var update = Builders<Person>.Update
//Something here - how do I pass my person's properties?
.Set("lastModified", DateTime.Now)
.Inc("version",1);
await collection.UpdateOneAsync(query, update );
}
//--
//In real life this'll work for other types, this is for demonstration only
public class Person
{
public string name {get;set;}
public string surname {get;set;}
}
So how can I go about this, without, for instance, looping through properties using Reflection?
Not sure if you are able to do this but the Mongodb Driver provides something called [BsonExtraElements].
public class Person
{
public string name {get;set;}
public string surname {get;set;}
[BsonExtraElements]
public Dictionary<string,object> AdditionalFields { get; set; }
}
What will happen is that anything that cant be serialized to the model will be filled into that dictionary, no matter the type. You can add to it as well and remove.
This will add no additional overhead to your database, The only downside to this is that querying this dictionary is somewhat not a great experience as you may need to cast specific keys to their relevant expected types.
If this is not viable I suggest the BSON approach recommended by Simon.

Should I use a set to prevent items being added more than once to the collection by mistake?

Please see the code below:
public class Customer
{
private readonly IHashSet<Order> _orders = new Set<Order>();
public string FirstName { get; set; }
public string LastName { get; set; }
public string Province { get; set; }
public IEnumerable<Order> Orders
{
get { foreach (var order in _orders) yield return order; }
}
internal void AddOrder(Order order)
{
_orders.Add(order);
}
}
I am trying to decide whether the _orders property should be a List (which I would normally use) or a Set. The only reason a duplicate order would be added is if the client code added a duplicate by mistake. Does that warrant the use of a Set? Is that a valid use case for a Set?
Sure, this is a valid use case, if duplicate orders are not allowed.
Since you expose IEnumerable<Order> instead of IList<Order> you don't seem to be interested in keeping the insertion order, or let the caller use it like a list or array. So a HashSet<T> is perfect here. The database is the best place to ensure that no duplicates are added, but it's not wrong to check that also at client-side. On this way you can handle bugs early and report them in your logs.
public class Customer
{
private readonly HashSet<Order> _orders = new HashSet<Order>();
public IEnumerable<Order> Orders => _orders;
// ...
internal void AddOrder(Order order)
{
_orders.Add(order);
}
}
Note that you should override Equals+GetHasCode in Order, implement IEquatable<Order> or pass a custom IEquatable<Comparer> to the HashSet constructor.
You have tagged your question with domain-driven-design tag, so the answer should be given in this context.
There is a rule in DDD called "make explicit what is implicit". If you don't want to have duplicates in your orders, in my opinion you should add some simple code that makes this rule explicit. It can be just a simple vetoIfOrderIsDupicated private method or something similar. It will give you a chance to communicate your team mates (or even you in the future) that there is a rule which should not be broken. If you just change this collection to Set, it doesn't carry any information WHY this is a Set. In the future someone from your team (or you personally) will refactor this code for example from performance perspective and will change Set to some high performance List, but will loose the rule.
So answering your question: I recommend to make the rule explicit. And collection can be Set if you want.
Additionally and not correlated to question, I don't know your domain, but it seems to me, that Order is another Aggregate Root. If yes, you shouldn't reference both Aggregate Roots. Instead you should reference IDs of AggR. So _orders should be collection of OrderID.

LINQ: select certain object properties Into Same object

If I have an object A with many properties, out of which I only need a couple, I can boost performance by not transferring unnecessary data, i.e. selecting only the object properties I need into a new type B, either named or anonymous.
Now imagine I want to bind a list of those original objects A to, say, a datagridview, which only displays the couple of properties I want. I have created the datagridview columns using the property names of the original object A and set its datasource type to typeof(A). I was wondering, if I can select into the same object A just omitting the properties I don't need, i.e.
public class MyObject
{
public string prop1 { get; set; }
public string prop2 { get; set; }
.....
public string propN { get; set; }
}
var list = context.MyObject
.Select(n => new MyObject { prop1 = n.prop1, prop2 = n.prop2 }).ToList();
In this way I don't need to define a new type, either named or anonymous. The question is, do I gain something in performance, or I still have the overhead of the original large object A information, although I do not transfer data for all its properties.
Alex
Actually, I think, the performance can't improve much as Select statement will go through all your list and create a new list of objects for you. But if you have reference property that you don't use. You can save there.
If there is no complicated logic when you show data to UI. Whey don't you keep the model as it is.
If this is for UI display only - there is no performance gain. Whatever time you might gain you will lose by creating a new list of anonymous types.
However, if you intend to send this object through the network (as a response to a request for example), then this makes sense. This way fewer properties have to be serialized and sent through the network.
In most cases, however, you should worry with performance to this level. The user won't notice an improvement on such a level. If you really wish to improve the performance of your application, you should profile it and find the hotspots.
The only meaningful performance gain, assuming your constructor is "cheap", is in the SQL and data transport from/to.
That said, not everything is about performance. Sometimes it's about clarity, extensibility, decoupling, etc. Clarity wise, you're forcing others to have to ask the question "Is this property used by the UI?"
In addition to clarity issues, you have coupling between the UI and back-end entities. This is not ideal. A cheap/temporary solution might simply be one like this. Keeping in mind that it's still coupled due to the interface on the class, but it's something that would be trivial to adjust in the future if desired.
public interface IMyModel
{
string prop1 { get; set; }
string prop2 { get; set; }
}
public class MyObject : IMyModel
{
public string prop1 { get; set; }
public string prop2 { get; set; }
.....
public string propN { get; set; }
}
IEnumerable<IMyModel> list = context.MyObject
.Select(n => new { n.prop1, n.prop2 }) // only select these properties
.ToArray() // execute the query
.Select(n => (IMyModel)new MyObject { prop1 = n.prop1, prop2 = n.prop2 }); // construct our desired object

C Sharp Object creating and referencing only 1 object in another class

I need to implement 1..* and 1..1 relationships in a store scenario application.(Classes: Member, Order, OrderLine, Product, Program, User) How do i go about a 1 user only having 1 Order that can have many OrderLines (preferably using a List structure?
This is my User class:
namespace ConsoleApplication1
{
public class User
{
private string ffName;
private string llName;
private int id = 0;
//Constructor
public User(string firstName, string lastName)
{
fName = firstName;
lName = lastName;
}
public User() {}
//Overrides
public override bool Equals(object obj)
{
return obj.ToString() == this.ToString();
}
public override int GetHashCode()
{
return this.ToString().GetHashCode();
}
public override string ToString()
{
string myUser;
myUser = string.Format("First Name: {0}; Last Name: {1}", fName, lName);
return myUser;
}
// Properties
public string fName
{
get
{
return ffName;
}
set
{
ffName = value;
}
}
public string lName
{
get
{
return llName;
}
set
{
llName = value;
}
}
}
}
You can have an Order class and an OrderLine class. The Order class will have a List of OrderLines and the User class can have a Order member.
Something like:
public class User
{
private string ffName;
private string llName;
private int id = 0;
private Order order = null;
//Constructor
public User(string firstName, string lastName)
{
fName = firstName;
lName = lastName;
}
...
}
public class Order
{
List<OrderLine> orderLines = null;
}
public class OrderLine
{
}
You have to implement the Order and the OrderLine class as:
class OrderLine
{
//some code
}
class Order
{
List<OrderLine> lstOrderLine;
//some code
}
Then add the Order class to your user class.
Edit: Removed snarkyness and attitude :)
First you need an order (hint you are going to need a class for that). Now the order needs to be attched to a user. So add a field of type User. That takes care of one order one user. (Note that a user can make more than one order)
So now you order is missing lines. Add another member variable that is a list of line types. Now in your order you need to add methods to add, remove and query order lines.
Edit: The question was raised what was meant by "add a field". Add a field means add a property or private member. When you are doing this you are doing the technical term of composition. Composition is commonly explained as a "has a" relationship. So an order "has a user" and "has a list of order lines"
Class User()
{
public string firstName { get; set; }
public string lastName {get; set; }
public int id { get; set;}
}
Class OrderLine()
{
}
Class Order()
{
private List<OrderLine> orderLines;
public User submitter { get; set;}
public Order()
{
orderLines = new List<OrderLine>();
}
public void AddOrderLine(OrderLine newOrderLine)
{
this.orderLines.Add(newOrderLine);
}
public IList<OrderLine> GetOrderLines()
{
return this.orderLines;
}
}
Example
User customer1 = new User();
// Initialize customer1 values...
Order someOrder = new Order();
someOrder.submitter = customer1;
someOrder.AddOrderLine(new OrderLine());
EDIT: Changed Member class to User class
Your most recent comment cleared up your question:
Its not hard to create each one i just dont understand how to get the relationship to work with 1..* or 1..1. If i create an Order i can always create another order
So, let's talk about the types of relationships.
Relationship types
Relationship types don't talk about absolute numbers of entities in the system. They just talk about numbers of entities in relation to other entities.
1:1 Relationship
This means that the two entity types must exist in pairs. If one entity of type A exists, then only one entity of type B can exist. For example, your User and Order. An order can't exist without a User, and a User can only have one Order. This doesn't mean there is only one User - there could be 42 users. This just means that if an Order exists, a User must also exist, and that the User can only have one Order.
There is a strict and less strict version of this. Technically, I just described something like a 1:{0 or 1} relationship. In a real 1:1 relationship you would require that the Order exists if the User exists. Neither could exist if the other didn't exist. However this constraint is usually relaxed when talking about relational databases (but only in one direction - in this case you still can't have an Order without a User).
You can model this relationship with code like this:
public class User
{
public Order Order { get; set; }
}
public class Order
{
// You could put a reference here back to the User if you want...
}
Note that it is a bit weird to only support only one Order for a User. It makes more sense to make it 1:*. But if that is a requirement of your assignment, then this is how you'd model it.
1:* Relationship
This is similar to the 1:1 relationship. But it relaxes some of the restrictions so that if an entity of type A exists, then any number (including zero) of type B can exist. The example is the Order and OrderLine. Again, there is no restriction on how many of either entity type exist. There could be 57 orders in the system. You just can't have an OrderLine without an Order, and there could be multiple OrderLines per Order.
You can model this relationship with code like this:
public class Order
{
public List<OrderLine> OrderLines { get; set; }
}
public class OrderLine
{
// You could put a reference here back to the Order if you want...
}
Enforcing relational concepts in code
I can't speak for your assignment, so make sure you back up what I am saying here against what your assignment requires.
You should not try to enforce basic relational concepts like these in code. The database is better at it, has better (declarative) language to describe the relationships, and is going to be your ultimate source of data for the system.
Instead, you should just do a soft model that follows the relationships (as the code samples above do), and let the database do the real policing of those constraints.
Examples:
You should not try to restrict construction of Order types in code, and you shouldn't require a User to exist to construct an Order (as code entities).
You should not require an Order to exist to create an OrderLine (as code entities).
Trying to put these sorts of restrictions in code buys you nothing. When you persist the entities to the database, the database will ensure these relationships for you (assuming you've set it up correctly, which you will learn to do). Your error will be caught, and you'll learn habits that avoid these types of errors very quickly.
Trying to put these sorts of restrictions in code hurts you. It will be harder to write your program, and it will be harder to write unit tests for your code.
For example, consider an algorithm or test that compares OrderLine values. Maybe you want it to compare to a hypothetical OrderLine. If you had relational restrictions in place in your code, you'd also have to create a hypothetical Order and User. Would you also compare the hypothetical User and Order to the real ones? What if your algorithm shouldn't care what User or Order it originated from? If you're not going to compare them, why bother creating them to begin with?
So: Don't worry about it. Softly model your relationships so that it is easy to navigate between your objects, and let the database do your strict relationship validations for you.

Categories