How do I make a collection fast searchable? - c#

EDIT: I rephrased the question, and it was solved on this post: How do I search within a collection of type ConfigurationSection?
Original Question:
I am storing a list of config options in my web config. I may have 50 or 100 items in here eventually.
I am using the method described here:
http://net.tutsplus.com/tutorials/asp-net/how-to-add-custom-configuration-settings-for-your-asp-net-application/
The good news:
It works, and I have a _Config collection that has all the
The problem: How do I query _Config for a specific feed? (I will have 50-100, maybe more over time.... someday this will move to a db, but not now, as it is hosted on azure, and I need to avoid azure persistence for now.)
(And since this will execute a lot, perhaps it should be hashtable or dictionary? but I don't know how to create em...)
I have struggled, and have been unable to cast _Config into a list or something that I can query.
The question is: How do I get _Config (from the link above) into something that I can query for a specific feed?
The ultimate goal is to have a func that is called to work with a specific feed, and so it needs the config info just from that feed record. In pseudocode, the goal is something like:
getFeed(feedname)
if (_Config.name == feedname) // e.g. feedname is one of the "name" elements in the web.config
// do the stuff
GetData(_Config.feedname.url)
else
// requested feed is not in our config
// tell use can't do it
Or, (also pseudo code)
getFeed(feedname)
try
thisPassFeed = _Config.feedname;
string url = thisPassFeed.url;
// do the stuff
GetData(url);
catch
// requested feed is not in our config
// tell use can't do it
return("can't find that feedname in web.config")

You could create a static class that has a private Dictionary member. In the static constructor access the _Config and do
public static class Feeds
{
private static readonly Dictionary<string, FeedElement> feeds;
static Feeds()
{
feeds = new Dictionary<string, FeedElement>();
var config = ConfigurationManager.GetSection("feedRetriever") as FeedRetrieverSection;
foreach (FeedElement feed in config.Feeds)
{
feeds.Add(feed.Name, feed);
}
}
static public FeedElement GetFeed(string name)
{
return feeds[name];
}
}

Related

Variable scope abstraction

I need 'static' variable that scope is per query, not per application. I describe it a little bit more below so:
I've got some process that evaluates queries. Each query requires it's own ID and I can process multiple queries in parallel. It basically looks like:
OnServiceStart(){
var env = new Environement();
env.SetValue(...);
...
}
ProcessQuery(string query){
var id = Guid.NewId();
var evaluator = CreateEvaluatorBasedOnQuery();
evaluator.Evaluate();
}
I also have very simple class that holds my environment variables:
public class Environment
{
private static readonly ConcurrentDictionary<string, object> Objects;
static Environment()
{
Objects = new ConcurrentDictionary<string, object>();
}
public T Value<T>(string name)
{
return (T) Objects[name];
}
public void SetValue<T>(string name, T value)
{
if (!Objects.TryAdd(name, value))
Objects.TryUpdate(name, value, Objects[name]);
}
...
}
Environment is set up with values like:
env.SetValue(EnvironmentServiceHelper.PluginsFolderKey, ApplicationConfiguration.PluginsFolder);
env.SetValue(EnvironmentServiceHelper.HttpServerAddressKey, ApplicationConfiguration.HttpServerAdress);
env.SetValue(EnvironmentServiceHelper.ServerAddressKey, ApplicationConfiguration.ServerAddress);
env.SetValue(EnvironmentServiceHelper.TempFolderKey, Path.GetTempPath());
However EnvironmentServiceHelper.TempFolderKey needs to be slightly different per query so instead Path.GetTempPath() I would like it to be $"{Path.GetTempPath()}\{id}".
My requirement is that it should be completelly transparent for evaluator classes. I can't pass id so code like that is not valid.
Environment env = new Environemnt();
env.GetValue(...)
evaluator.Evaluate(id);
GetValue(...) must returns $"{Path.GetTempPath()}\{id}" where id is different for each query.
Can't get it how to build appropriate abstraction to approach this. Currently, I would like to avoid achieving it by separating with different AppDomain. Could someone hints me something?
Why not create a layered Environment? The inside environment keeps the global properties, the outside environment the query specific ones? This object is passed along to every method requiring it.
You start of with a constructor like this:
Environment env = new Environment(originalEnvironment);
Depending on your wishes, you can copy all values from the originalEnvironment to the newly instantiated Environment, or keep a reference.

Update Cache with one item C#

I am getting users and their data from external webservice. I cache those items because I don't want to hit web service every time. Now, If user update any of their information, I am saving it through webservice. But I don't want to get the latest data from web service as it takes lot of time. Instead I want to update my cache. Can I do that ? If so, what would be the best way ? Here is my Code
List<User> users = appSecurity.SelectUsers();
var CacheKey = string.Format("GetUserList_{0}", currentUser);
CacheFactory.AddCacheItem(CacheKey, users, 300);
CacheFactory is a class where I handle Adding, Clearing and Removing cache. Below is the code
public static void RemoveCacheItem(string key)
{
Cache.Remove(key);
}
public static void ClearCache()
{
System.Collections.IDictionaryEnumerator enumerator = Cache.GetEnumerator();
while (enumerator.MoveNext())
{
RemoveCacheItem(enumerator.Key.ToString());
}
}
public static void AddCacheItem<T>(string key, T value, double timeOutInSeconds)
{
var Item = GetCacheItem<T>(key);
if (Item != null)
{
RemoveCacheItem(key);
Item = value;
}
Cache.Insert(key, value, null, DateTime.Now.AddSeconds(timeOutInSeconds), System.Web.Caching.Cache.NoSlidingExpiration);
}
The answer is yes, it can be done. It can also be done in many different ways depending on what you want to solve. At the basic level you can create a cache by using a List<T> or Dictionary<T,T> to store your data.
When you get information from the external web-service, you push the data into your List or Dictionary. You can then use that data throughout your application. When you need to update that cache, you update the value in the List/Dictionary.
You can update your dictonary like so
Dictionary<string, int> list = new Dictionary<string, int>();
then you can set the value for the key "test" as follows
list["test"] = list["test"] + 1;
When you are ready to push the updated data to the external source. All you need to do is properly parse that data into the format the source is expecting and send away.
Like I said there are many different ways to do this, but this is a basic sample way to accomplishing it. You can use this example to build off and go from there.

Storing global variables in c#?

I basically have created a class which when a user logs into a website it then queries the database and stores some settings in a List (So I have key/pair values).
The reason for this is because I want to always be able to access these settings without going to the database again.
I put these in a class and loop through the fields via a SQL query and add them to the list.
How can I then access these variables from another part of the application? or is there a better way to do this? I'm talking server side and not really client side.
Here is an example of what I had at the moment:
public static void createSystemMetaData()
{
string constring = ConfigurationManager.ConnectionStrings["Test"].ConnectionString;
SqlConnection sql = new SqlConnection(constring);
sql.Open();
SqlCommand systemMetaData = new SqlCommand("SELECT * FROM SD_TABLES", sql);
//Set Modules
using (SqlDataReader systemMetaDataReader = systemMetaData.ExecuteReader())
{
while (systemMetaDataReader.Read())
{
var name = systemMetaDataReader.GetOrdinal("Sequence").ToString();
var value = systemMetaDataReader.GetOrdinal("Property").ToString();
var Modules = new List<KeyValuePair<string, string>>();
Modules.Add(new KeyValuePair<string, string>(name, value));
}
}
}
Thanks
Any static properties of a class will be preserved for the lifetime of the application pool, assuming you're using ASP.NET under IIS.
So a very simple class might look like:
public static class MyConfigClass
{
public static Lazy<Something> MyConfig = new Lazy<Something>(() => GetSomethings());
public static Something GetSomethings()
{
// this will only be called once in your web application
}
}
You can then consume this by simply calling
MyConfigClass.MyConfig.Value
For less users you can go with the SessionState as Bob suggested,however with more users you might need to move to a state server or load it from Data Base each time.
As others have pointed out, the risk of holding these values in global memory is that the values might change. Also, global variables are a bad design decision as you can end up with various parts of your application reading and writing to these values, which makes debugging problems harder than it need be.
A commonly adopted solution is to wrap your database access inside a facade class. This class can then cache the values if you wish to avoid hitting the database for each request. In addition, as changes are routed through the facade too, it knows when the data has changed and can empty its cache (forcing a database re-read) when this occurs. As an added bonus, it becomes possible to mock the facade in order to test code without touching the database (database access is notoriously difficult to unit test).
From the looks of things you are using universal values irrespective of users so an SqlCacheDependency would be useful here:
Make sure you setup a database dependency in web.config for the name Test
public static class CacheData {
public static List<KeyValuePair<string,string>> GetData() {
var cache = System.Web.HttpContext.Current.Cache;
SqlCacheDependency SqlDep = null;
var modules = Cache["Modules"] as List<KeyValuePair<string,string>>;
if (modules == null) {
// Because of possible exceptions thrown when this
// code runs, use Try...Catch...Finally syntax.
try {
// Instantiate SqlDep using the SqlCacheDependency constructor.
SqlDep = new SqlCacheDependency("Test", "SD_TABLES");
}
// Handle the DatabaseNotEnabledForNotificationException with
// a call to the SqlCacheDependencyAdmin.EnableNotifications method.
catch (DatabaseNotEnabledForNotificationException exDBDis) {
SqlCacheDependencyAdmin.EnableNotifications("Test");
}
// Handle the TableNotEnabledForNotificationException with
// a call to the SqlCacheDependencyAdmin.EnableTableForNotifications method.
catch (TableNotEnabledForNotificationException exTabDis) {
SqlCacheDependencyAdmin.EnableTableForNotifications("Test", "SD_TABLES");
}
finally {
// Assign a value to modules here before calling the next line
Cache.Insert("Modules", modules, SqlDep);
}
}
return modules;
}

Embedding a lot of constants in compile code or an external file

I'm developing scientific software that needs access to the periodic table of elements. An Element comprises of a set of Isotopes which have a few readonly properties (e.g. mass, abundance, atomic number, etc.). There are over 100 elements, and when factoring in their isotopes, there are well over 1000 isotopes. To populate all these objects at run time, I currently have an XML file (Build Action: Content)* containing all the elemental data that I parse in during the static constructor of the Element class:
public class Element {
private static readonly Dictionary<string, Element> _elements;
static Element()
{
_elements = new Dictionary<string, Element>();
LoadElements("Resources/Elements.xml"); // 461 KB file
}
static LoadElements(string resource) {
// code for construction of elements objects and population of the
// _elements dictionary.
}
private Element(blah) { \\ instance constructor }
}
This works, but there is a overhead in parsing in the file and I lose some flexibility in designing the Element class. The alternative is to hard-code each Isotope and Element into the static constructor. The advantage of the later is I would be able to add static readonly property for each Element (a useful feature):
public class Element {
private static readonly Dictionary<string, Element> _elements;
public static readonly Element Carbon = {get; private set;}
public static readonly Element Hydrogen = {get; private set;}
static Element()
{
_elements = new Dictionary<string, Element>();
Carbon = AddElement("Carbon", 6);
Carbon.AddIsotope(12, 12.0000000, 0.9893);
Carbon.AddIsotope(13, 13.0033548378, 0.0107);
Hydrogen = AddElement("Hydrogen", 1);
//Repeat this pattern for all the elements...
}
static Element AddElement(string name, double atomicNumber)
{
Element element = new Element(name, atomicNumber);
_elements.Add(name, element);
return element;
}
private Element(string name, double atomicNumber) {
// Not Important, just setting readonly properties
}
private void AddIsotope(int massNumber, double mass, double abundance) {
// Not Important;
}
}
However, this seems like a lot of hard-coded data to include in a class.cs file. So I am torn, on one hand it makes sense on a data management level to have the elemental data stored in an external file which is read in. But on the other hand, because all the data is really a bunch of constant/static readonly objects, this additional parsing work seems timely, unfruitful, and limits the API design. What is the correct way for creating all these objects?
*Note: the Build Action is set to Content for the case if the client wants to modify the values of the elements for whatever reason. This isn't a necessity and could be changed to an embedded resource.
I would consider putting the values in an embedded file, but possibly having an enum of the elements. (Probably not the isotopes, but provide an easy way of specifying an isotope from the elements.)
That way:
You can still have a strongly-typed API, and not rely on magic strings etc in user code
You can still make it easy to change the data later should you really wish to (and possibly supply a way of reading the data from an external source)
You probably make it easier to work with the data itself, as an XML file rather than C#
Don't worry about the parsing work - given that you only need to do it once, I find it hard to believe that it would be significant in terms of performance.
Check out the blue obelisk project which is hosted on sourceforge - I think you'll find some useful stuff there, possibly even exactly what you're looking for.

Api client that fetches global configuration from web.config

In my application I want to do something like:
SomeApiClient apiClient = new SomeApiClient();
List<User> apiClient.getUsers();
In my web.config, I will a few configuration key/value pairs.
How can I write the constructor of SomeApiClient in such a way that it loads the values from the web.config, but not each time, only once when the application starts or first request?
Here ya go.
namespace dm2
{
using System.Collections.Specialized;
using System.Configuration;
public class SomeApiClient
{
internal static NameValueCollection Config
{
get
{
if (config == null) config = ConfigurationManager.AppSettings;
return config;
}
}
internal static NameValueCollection config;
}
}
Basically you just use a static property in a non static class...so in order to get your config settings,
public void DoFunConfigStuff()
{
for (var i = 0; i < Config.Count;i++ )
{
Console.WriteLine("[{0}]: {1}",Config.Keys[i] ,Config[i]);
}
}
Since you mentioned web.config, I'm assuming this is a web app. So I'd like to point out that you should expect that your app pool could be recycled at any time, at which point this would cause the static getter to reevaluate and load new settings. It's best not to reply on this.
One thing you could do is serialize this info to some medium, be it disk or database, and then have some kind of db switch, or webpage that will force a reload.
So in that getter it would check for the serialized data, if it doesn't exist, check web.config, and then save that data somewhere. Next time it gets recycled it will then pick up the old data. Really depends on your setup I suppose.

Categories