I'm new to c#, but I need to change an existing program, by merely changing the connection string. The idea is to redirect the connection to a test database environment. I've found that the code uses a dll to create a connection to the server. I used Jetbrains Dotpeek to look inside the dll, but I could only see methods and functions, but nowhere could I see the connection detail to change it.
What ways are there of encrypting a connection string? Are there special files used generally for this, that I can look for?
To give more elaborate information:
In the normal code in the cs file, there is for example this:
var result = new LibSqlQuery(Db.ABC.ConnectionString, sql);
return result;
and Db is a method in a dll defined as following:
public static class Db
{
private static Dictionary<string, LibDbConnection> _connections = new Dictionary<string, LibDbConnection>();
private static LibDbConnection GetConnection(string connectionName)
{
lock (Db._connections)
{
if (!Db._connections.ContainsKey(connectionName))
Db._connections.Add(connectionName, new LibDbConnection(connectionName));
}
return Db._connections[connectionName];
}
public static LibDbConnection ABC => Db.GetConnection("conABC");
public static LibDbConnection CDE => Db.GetConnection("conCDE");
}
where ABC and CDE are database environments.
I found another config file, which had the connections. This can be closed now. Thank you.
Related
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;
}
I've got an MVC3 project and one of the models is built as a separate class library project, for re-use in other applications.
I'm using mini-profiler and would like to find a way to profile the database connections and queries that are made from this class library and return the results to the MVC3 applciation.
Currently, in my MVC3 app, the existing models grab a connection using the following helper class:
public class SqlConnectionHelper
{
public static DbConnection GetConnection()
{
var dbconn = new SqlConnection(ConfigurationManager.ConnectionStrings["db"].ToString());
return new StackExchange.Profiling.Data.ProfiledDbConnection(dbconn, MiniProfiler.Current);
}
}
The external model can't call this function though, because it knows nothing of the MVC3 application, or of mini-profiler.
One way I thought of would be to have an IDbConnection Connection field on the external model and then pass in a ProfiledDbConnection object to this field before I call any of the model's methods. The model would then use whatever's in this field for database connections, and I should get some profiled results in the MVC3 frontend.
However, I'm not sure if this would work, or whether it's the best way of doing this. Is there a better way I'm missing?
ProfiledDbConnection isn't dapper: it is mini-profiler. We don't provide any magic that can take over all connection creation; the only thing I can suggest is to maybe expose an event in your library that can be subscribed externally - so the creation code in the library might look a bit like:
public static event SomeEventType ConnectionCreated;
static DbConnection CreateConnection() {
var conn = ExistingDbCreationCode();
var hadler = ConnectionCreated;
if(handler != null) {
var args = new SomeEventArgsType { Connection = conn };
handler(typeof(YourType), args);
conn = args.Connection;
}
return conn;
}
which could give external code the chance to do whatever they want, for example:
YourType.ConnectionCreated += (s,a) => {
a.Connection = new StackExchange.Profiling.Data.ProfiledDbConnection(
a.Connection, MiniProfiler.Current);
};
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];
}
}
I am building an application with c# and I decided to use the Enterprise Library for the DAL (SQL Server).
I don't remember where, but I had read an article about EntLib which said that the connections are closed automatically.
Is it true?
If not, what is the best approach of managing the connections in the middle layer?
Open and close in each method?
The above is a sample method of how I am using the EntLib
public DataSet ReturnSomething
{
var sqlStr = "select something";
DbCommand cmd = db.GetSqlStringCommand(sqlStr);
db.AddInParameter(cmd, "#param1", SqlDbType.BigInt, hotelID);
db.AddInParameter(cmd, "#param2", SqlDbType.NVarChar, date);
return db.ExecuteDataSet(cmd);
}
Thanks in advance.
the ExecuteDataSet method returns a DataSet object that contains all the data. This gives you your own local copy. The call to ExecuteDataSet opens a connection, populates a DataSet, and closes the connection before returning the result
for more info:
http://msdn.microsoft.com/en-us/library/ff648933.aspx
I think you should have something like a static class used as a Façade which would provide the correct connection for your library subsystems.
public static class SystemFacade {
// Used as a subsystem to which the connections are provided.
private static readonly SystemFactory _systemFactory = new SystemFactory();
public static IList<Customer> GetCustomers() {
using (var connection = OpenConnection(nameOfEntLibNamedConnection))
return _systemFactory.GetCustomers(connection);
}
public static DbConnection OpenConnection(string connectionName) {
var connection =
// Read EntLib config and create a new connection here, and assure
// it is opened before you return it.
if (connection.State == ConnectionState.Closed)
connection.Open();
return connection;
}
}
internal class SystemFactory {
internal IList<Customer> GetCustomers(DbConnection connection) {
// Place code to get customers here.
}
}
And using this code:
public class MyPageClass {
private void DisplayCustomers() {
GridView.DataSource = SystemFacade.GetCustomers();
}
}
In this code sample, you have a static class that provides the functionalities and features of a class library. The Façade class is used to provide the user with all possible action, but you don't want to get a headache with what connection to use, etc. All you want is the list of customers out of the underlying datastore. Then, a call to GetCustomers will do it.
The Façade is an "intelligent" class that knows where to get the information from, so creates the connection accordingly and order the customers from the subsystem factory. The factory does what it is asked for, take the available connection and retrieve the customers without asking any further questions.
Does this help?
Yes, EntLib closes connections for you (actually it releases them back into the connection pool). That is the main reason why we originally started to use EntLib.
However, for all new development we have now gone on to use Entity Framework, we find that much more productive.
I have a DAL class library that is included in my program as a DLL. The below line is from the DAL to initialize the connection.
DataSet ds = new DataSet("table");
SqlConnection cnn = new SqlConnection(Settings.CMOSQLConn);
When I run this I get the below error:
An unhandled exception of type 'System.StackOverflowException' occurred in CMO.DAL.dll
The below is in the Settings.Designer.cs file and it is where it shows the error on the get call:
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.SpecialSettingAttribute(global::System.Configuration.SpecialSetting.ConnectionString)]
[global::System.Configuration.DefaultSettingValueAttribute("Data Source=WWCSTAGE;Initial Catalog=CMO;Persist Security Info=True;User ID=CMOWe" +
"bService;Password=ecivreSbeWOMC")]
public static string CMOSQLConn {
get {
return (CMOSQLConn);
}
}
Anyone have any ideas of what to look for? Is it because the connection string is stored in the dll instead of my Main App? I am really stuck on this and will greatly appreciate any help!
EDIT 1
I tried Greg's suggestion below:
public static string CMOSQLConn {
get {
return (Settings.CMOSQLConn);
}
}
And I still get the same error... Any more thoughts? Thanks so far!
EDIT 2
So I followed the suggestion of regenerating the settings file below and now my setting file looks like this -->
public string CMOSQLConn {
get {
return ((string)(this["CMOSQLConn"]));
}
}
Unfortunately this won't compile now as wherever I have this statement -->
SqlConnection cnn = new SqlConnection(Settings.CMOSQLConn);
I now get this error -->
Error 1 An object reference is required for the non-static field, method, or property 'CMO.DAL.Properties.Settings.CMOSQLConn.get' B:\MyDocs\tmpPATRIOT\Projects\VS2008\DisConnectDAL\CMO.DAL\SupportWorker.cs 13 51 CMO.DAL
Is this what I should expect?
Thanks!
This is a classic c# properties mistake. Double check what you're returning in your property-- you're returning the property itself! Name resolution will prefer the local name over an external name. You're getting a stack overflow because you hit infinite recursion when CMOSQLConn.get calls CMOSQLConn.get.
Consider returning Settings.CMOSQLConn. The extra specification should clearly indicate the correct location of your connection string.
EDIT:
Whoops! I didn't notice that you pasted that from your Settings designer file. The infinite recursion is clearly happening, but I'm afraid you'll have to do some more investigation to track down why it's happening in this case.
It appears that your designer file was generated incorrectly (!!!). On VS2008, my settings designer getters look something like:
public bool Foo{
get {
return ((bool)(this["Foo"]));
}
// ...
}
You may need to do something similar. IE:
public string CMOSQLConn
get {
return ((string)(this["CMOSQLConn"]));
}
// ...
}
Try changing your code to this:
public static string CMOSQLConn {
get {
return ((string)(this["CMOSQLConn"]));
}
}
Hmm.. Good point in the comments. I just looked in my VS settings file and copied and pasted without thinking. Something isn't right with your settings file... It shouldn't be creating a static property for the settings.