Project type: ASP.NET Website
Currently we are employing a set of lookup data stored as an XML file inside the project to fill data on a certain ASPX page.
We're looking at changing this approach to the one below citing efficiency:
Store the XML file values in Database. Fetch the values from Database on application start (Global.asax). Store in an in-memory object like LIST or HASHTABLE and Use this further.
Is this a valid approach? Is there something that could be done better?
If you need any more details, please leave a comment below. I'll be happy to share.
If you need read only access, you can declare a static variable in the global.asax and use the Application_Start event.
Related
My goal is to implement the changing values of resources and give the admin the ability to maintain the language through the portal. In order to do that, I need to be able to change resx files at the runtime, because all their values are stored on the resx files. I have 3 resx files for each different language. In my case I want the translation can be maintain later by an admin at runtime. For example admin can add, edit or delete the entry for the language at runtime.
As #Xerillio mentioned in his comment this is a lot of effort.
Recently I've created a nuget that may save your time and effort. Have a look at XLocalizer, it creates resources and uses online translation services to auto translate the missing resources and save them in XML or DB, then it provides an easy interface to export them to RESX. Finally you may see XLocalizer.Samples, it contains sample setup for different scenarios.
If you need another file/DB type to store the resources, you may create your custom resource provider and register it in startup.
The DB sample provides UI to edit resources, but with XML sample I didn't create a UI for editing resources, instead you may download the XML, do your corrections if any, then upload and use the built-in exporter to export to RESX.
With this nuget, all I have to do to add a new culture even in runtime, is just to add the culture name to the supported cultures list, then do some correction to the auto translations, all the rest is handled by XLocalizer.
Notice: it was not possible to put all this in the comment, thats why I posted as answer :)
Currently in my Asp.Net website I store localization texts in a table in the database. The table has three columns:
TextCode nvarchar(100),
CultureId int,
TextString nvarchar(MAX)
So every time when I need to get a localized text for a specific culture I just do a simple query.
The main advantage of this method is simple and also I can update the texts while my web app is running.
The obvious drawback is performance. I use resource files for localization in other desktop applications. The reason I chose database is I am under an impression that updating the resource file in asp.net will cause the web app to reload and thus I need to take the site offline when I update the resource file. Is assumption true? What's the "common" approach to store localized texts in Asp.Net?
Thanks
Common approach is to use Global and Local resource files. If you want to use database consider using asp.net cache with sql cache dependency. In application start, load all your resource data from sql server and store it in cache, and create a utility class to return data from cache based on resource key.
I currently hold my resources in a database instead of resx files. I would like to be able to test whether all keys used in the application are held in the database to avoid runtime errors.
I have a custom ResourceProviderFactory to accomplish retrieving the resources.
Resources could be in aspx view pages - GetLocalResourceObject("ResourceKey") or GetGlobalResourceObject("ResourceClass", "ResourceKey").
They could be in a controller - HttpContext.GetGlobalResourceObject("ResourceClass", "ResourceKey").
I also call the resources from the core assemblies of my application without using the ASP.NET resource factory (using a singleton instead) - CoreResources.Current.GetResource("ResourceClass", "ResourceKey")
What would be the best way for me to ensure that all resources are in the database without having to waiting for a runtime exception?
The only approach I can think of is writing an app that scans your source code files and extracts all the resource keys you are using. You can then check the existence of each key in your database.
Unfortunately it is not so trivial... I don't think there is an easier way.
I would however change your ResourceProviderFactory to not throw an exception in case of a missing key. Just return some text like "Resource missing: 'xxx'" and log it so that it can be added.
Folks,
I have an ASP.NET project which is pretty n-tier, by namespace, but I need to separate into three projects: Data Layer, Middle Tier and Front End.
I am doing this because...
A) It seems the right thing to do, and
B) I am having all sorts of problems running unit tests for ASP.NET hosted assemblies.
Anyway, my question is, where do you keep your config info?
Right now, for example, my middle tier classes (which uses Linq to SQL) automatically pull their connection string information from the web.config when instantiating a new data context.
If my data layer is in another project can/should it be using the web.config for configuration info?
If so, how will a unit test, (typically in a separate assembly) provide soch configuration info?
Thank you for your time!
We keep them in a global "Settings" file which happens to be XML. This file contains all the GLOBAL settings, one of which is a connection string pointing to the appropriate server as well as username and password. Then, when my applications consume it, they put the specific catalog (database) they need in the connection string.
We have a version of the file for each operating environment (prod, dev, staging, etc). Then, with two settings -- file path (with a token representing the environment) and the environment -- I can pick up the correct settings files.
This also has the nice benefit of a 30 second failover. Simple change the server name in the settings file and restart the applications (web) and you have failed over (of course you have to restore your data if necessary).
Then when the application starts, we write the correct connection string to the web.config file (if it is different). With this, we can change a website from DEV to PROD by changing one appSettings value.
As long as there isn't too much, it's convenient to have it in the web.config. Of course, your DAL should have absolutely no clue that it comes from there.
A good option is for your data layer to be given its config information when it is called upon to do something, and it will be called upon to do something when a web call comes in. Go ahead and put the information in your web.config. In my current project, I have a static dictionary of connection strings in my data layer, which I fill out like so in a routine called from my global.asax:
CAPPData.ConnectionStrings(DatabaseName.Foo) =
ConfigurationManager.ConnectionStrings("FooConnStr").ConnectionString()
CAPPData.ConnectionStrings(DatabaseName.Bar) =
ConfigurationManager.ConnectionStrings("BarConnStr").ConnectionString()
etc.
"Injecting" it like this can be good for automated testing purposes, depending on how/if you test your DAL. For me, it's just because I didn't want to make a separate configuration file.
For testing purposes don't instantiate DataContext with default ctor. Pass connection string info to constructor.
I prefer to use IoC frameworks to inject connection to data context then inject context to other classes.
I have an application that must be accessed for many users.
To optimize the performance I intend to store each user profile information at a independant database file.
I need everytime a user login the application, to setup a new provider linked with his own database.
All databases have the same structure. So while querying user the commom generated DAL classes must switch for the database file relative the the user.
Is there a way for configure SubSonic for doing that switch at runtime?
Thanks.
Well, assuming we 're talking about SubSonic3:
I have made a patch for this and logged it as an issue in the SubSonic Templates project on github, where the source is available. You can find the issue (and a link to the code) here.
After you apply the patch, you will have a new DefaultDataProvider property which does exactly what you want. Use it like this (e.g. after a user logs in):
YourSubSonicGeneratedNamespace.YourDatabaseName.DefaultDataProvider =
SubSonic.DataProviders.ProviderFactory.GetProvider(
"your connection string here",
SubSonic.DataProviders.DbClientTypeName.SqlLite);
And you 're good to go.
For SubSonic 2, this answer sounds like what you want.
With subsonic 2 I use an approach where I inject the provider at runtime rather than loading it from the app.config file.
Look at my answer here: Subsonic in a VS2008 Add-In woes
Instead of just using one provider you could create one for every user who starts the application and change the default provider as needed.