I would love to remove all items from MemoryCache.
What I have tried already:
var listDBCalls = ((FixedSizedQueue<DalCacheDto>)MemoryCache.Default.Get($"DAL_CACHE_{HttpContext.Current?.User?.Identity?.Name}"))?.ToList();
listDBCalls.clear();
If I watch this code in debugger, it shows that listDBCalls is really empty. But, calling again:
((FixedSizedQueue<DalCacheDto>)MemoryCache.Default.Get($"DAL_CACHE_{HttpContext.Current?.User?.Identity?.Name}"))?.ToList()
is showing me that all items are still there. Why is that?
Avoid to use the default memory cache to have more control.
Create your own memory cache (by example as a static property of a static class) and when you need to erased it you can simply create a new one to replace the older one. Don't forget to call the dispose method.
It seems the way to go : How to clear MemoryCache?
Edit
When I read you code I'm not sure what you want to do.
If you want to remove a particular entry (which seems the case) you can use the remove method.
MemoryCache.Default.Remove($"DAL_CACHE_{HttpContext.Current?.User?.Identity?.Name}")
Related
probably a stupid question, but: Is there any way to reliable apply changes to a Roslyn workspace concurrently? And if not, what is the best practice to ensure it's done in correct order?
Example: Say you have some solution loaded into a Workspace, and have a basic function that will add a new project to the solution:
private Workspace _workspace;
// This is not thread-safe, right?
void AddProject()
{
var project = _workspace.CurrentSolution.AddProject(/* ... */);
_workspace.TryApplyChanges(project.Solution);
}
First question: Correct me if wrong, but I think AddProject would not be thread-safe, is that correct?
For example, lets say you want to add to new projects concurrently. So you call AddProject() twice concurrently.
My understanding is there is a race condition, and you might end up with both projects added (if one of the calls completes TryApplyChanges before the other call reaches _workspace.CurrentSolution), or only one of the projects added (if both calls have reached _worksapce.CurrentSolution before either has executed TryApplyChanges).
Second question: If my understanding is correct, then is there any best way to avoid these concurrency issues? I suppose the only real way would be to schedule/execute each modification sequentually, right?
How does Visual Studio, for example, do this.. Are modifications to the Workspace e.g. only done on the Dispatcher?
Thanks
The underlying code is thread-safe, but your usage is not.
TryApplyChanges() will return false if the solution changed in the meantime. If that happens, you need to try the changes again (starting from the new CurrentSolution).
Basically, you need to write
Solution changed;
do {
changed = _workspace.CurrentSolution....();
} while (!_workspace.TryApplyChanges(changed);
This is called a compare-and-swap loop; see my blog for more details.
I am storing a list of delegates in a dictionary, and then invoking them when required, problem is, when UI is no longer visible, the references to the delegates still exist, and when the UI shows up again, its a new instance, adds new references in addition to the old ones, thus calling twice the amount.
Design issues aside, is there a way of putting a constraint on a reference when storing it, to say that if the dictionary is the only place its stored then discard it and return null?
The best choice would be just .Clear() the dictionary when the UI becames invisible
I need to clear a Cache which is being used for a custom module in Sitecore, what's the best practice to clear it?
We're currently adding keys to the cache with
System.Web.HttpContext.Current.Cache.Add(key, obj, dependencyKey, DatTime.MaxValue);
This cache does not get cleared out on publish though and I need to clear it manually. I know it is possible to hook into Sitecores publish event, but need a way to clear it.
Tried removing keys with:
System.Web.HttpContext.Current.Cache.Remove(key);
But it did not do the trick
There is no .Clear() method.
You can iterate over all the entries and remove them by their key (or ID), using the GetEnumerator method of the Cache class.
IDictionaryEnumerator enumerator = Cache.GetEnumerator();
while(enumerator.MoveNext())
{
Cache.Remove(enumerator.Key);
}
I would run this code in a publish:end:remote event.
In the process of adhering to code analysis errors, I'm changing my properties to have private setters. Then I started trying to understand why a bit more. From some research, MS says this:
A writable collection property allows a user to replace the collection with a completely different collection.
And the answer, here, states:
Adding a public setter on a List<T> object is dangerous.
But the reason why it's dangerous is not listed. And that's the part where I'm curious.
If we have this collection:
public List<Foo> Foos { get; set; }
Why make the setter private? Apparently we don't want client code to replace the collection, but if a client can remove every element, and then add whatever they want, what's the point? Is that not the same as replacing the collection entirely? How is value provided by following this code analysis rule?
Not exposing the setter prevents a situation where the collection is assigned a value of null. There's a difference between null and a collection without any values. Consider:
for (var value in this.myCollection){ // do something
When there are no values (i.e. someone has called Remove on every value), nothing bad happens. When this.myCollection is null, however, a NullReferenceException will be thrown.
Code Analysis is making the assumption that your code doesn't check that myCollection is null before operating on it.
It's probably also an additional safeguard for the thread-safe collection types defined in System.Collections.Concurrent. Imagine some thread trying to replace the entire collection by overwritting it. By getting rid of the public setter, the only option the thread has is to call the thread-safe Add and Remove methods.
If you're exposing an IList (which would be better practice) the consumer could replace the collection with an entirely different class that implements IList, which could have unpredictable effects. You could have subscribed to events on that collection, or on items in that collection that you're now incorrectly responding to.
In addition to SimpleCoder's null checking (which is, of course, important), there's other things you need to consider.
Someone could replace the List, causing big problems in thread safety
Events to a replaced List won't be sent to subscribers of the old one
You're exposing much, much more behavior then you need to. For example, I wouldn't even make the getter public.
To clarify point 3, don't do cust.Orders.clear(), but make a function called clearOrders() instead.
What if a customer isn't allowed to go over a credit limit? You have no control over that if you expose the list. You'd have to check that (and every other piece of business logic) every place where you might add an order. Yikes! That's a lot of potential for bugs. Instead, you can place it all in an addOrder(Order o) function and be right as rain.
For almost every (I'd say every, but sometimes cheating feels good...) business class, every property should be private for get and set, and if feasible make them readonly too. In this way, users of your class get only behaviors. Protect as much of your data as you can!
ReadOnlyCollection and ReadOnlyObservableCollection exists only for read only collection scenearios.
ReadOnlyObservableCollection is very useful for one way binding in WPF/Silverlight/Metro apps.
If you have a Customer class with a List Property then this property should always have a private setter else it can be changed from outside the customer object via:
customer.Orders = new List<Order>
//this could overwrite data.
Always use the add and remove methods of the collection.
The Orders List should be created inside the Customer constructor via:
Orders = new List<Order>();
Do you really want to check everywhere in your code wether the customer.Orders != null then operate on the Orders?
Or you create the Orders property in your customer object as suggested and never check for customer.Orders == null instead just enumerate the Orders, if its count is zero nothing happens...
Refactoring some code again. Seeing some of this in one of the ASP.NET pages:
using (TextBox txtBox = e.Row.Cells[1].FindControl("txtBox") as TextBox)
{
}
There is no need to dispose txtBox, because it's just a reference to an existing control. And you don't want the control disposed at all. I'm not even sure this isn't harmful - like it would appear to ask for the underlying control to be disposed inappropriately (although I have not yet seen any ill effects from it being used this way).
TextBox inherits its implementation of IDisposable from its Component superclass. That implementation removes the component from its site container if it has one.
So, doing that might have nefarious effects if the text box actually resides in a site container. Also, after calling Dispose() on an object, you should not use it again, no matter what (it's not in a usable state anymore).
I'd suggest you avoid that pattern with ASP.NET web controls.
This is wrong, it shouldnt be used like this. I would imagine there are potential problems using this that wont show up immediately. The textboxes dispose is called upon leaving the using statement but it wont be garbage collected immediately. If it is collected then you will have problems later when you try to access that control.
The TextBox instance could potentially be null if not found, so Dispose() is called a NullReferenceException would be thrown.
I've never seen that pattern in practice, but if you need to use it, it'd be worth handling any potential errors.
There should be no negative secondary effects, but it's not necessary either. If we did using (x) { ... } on everything that implements IDisposable in the CLR most C# code would be unreadable.
Actually, here the TextBox instance is accessible only to the context inside the brackets of using statement, maybe that was the main reason of using it.
From MSDN:
Within the using block, the object
is read-only and cannot be modified
or reassigned.
So I guess you can only read the textbox properties, but not change them, inside the using block.