Red5: is it alright to store IConnection instances in a HashMap to retrieve later - red5

I have a HashMap defined like this
HashMap<String, IConnection> connections = new HashMap<String, IConnection>();
inside application connect, I add values into it like this:
conn.setAttribute(“username”, username);
connections.put(username, conn); // username and conn are parameters passed to
// connect method
inside application disconnect method, I remove values from it like this
connections.remove((String)conn.getAttribute(“username”));
This seems to work, however is it correct/safe? Or am I doing it wrong?

Yes, it is alright but I suggest that you make sure the connection is still connected before you try to access or write to it.

Related

this command is not available unless the connection is created with admin-commands enabled

When trying to run the following in Redis using booksleeve.
using (var conn = new RedisConnection(server, port, -1, password))
{
var result = conn.Server.FlushDb(0);
result.Wait();
}
I get an error saying:
This command is not available unless the connection is created with
admin-commands enabled"
I am not sure how do i execute commands as admin? Do I need to create an a/c in db with admin access and login with that?
Updated answer for StackExchange.Redis:
var conn = ConnectionMultiplexer.Connect("localhost,allowAdmin=true");
Note also that the object created here should be created once per application and shared as a global singleton, per Marc:
Because the ConnectionMultiplexer does a lot, it is designed to be
shared and reused between callers. You should not create a
ConnectionMultiplexer per operation. It is fully thread-safe and ready
for this usage.
Basically, the dangerous commands that you don't need in routine operations, but which can cause lots of problems if used inappropriately (i.e. the equivalent of drop database in tsql, since your example is FlushDb) are protected by a "yes, I meant to do that..." flag:
using (var conn = new RedisConnection(server, port, -1, password,
allowAdmin: true)) <==== here
I will improve the error message to make this very clear and explicit.
You can also set this in C# when you're creating your multiplexer - set AllowAdmin = true
private ConnectionMultiplexer GetConnectionMultiplexer()
{
var options = ConfigurationOptions.Parse("localhost:6379");
options.ConnectRetry = 5;
options.AllowAdmin = true;
return ConnectionMultiplexer.Connect(options);
}
For those who like me faced the error:
StackExchange.Redis.RedisCommandException: This operation is not
available unless admin mode is enabled: ROLE
after upgrading StackExchange.Redis to version 2.2.4 with Sentinel connection: it's a known bug, the workaround was either to downgrade the client back or to add allowAdmin=true to the connection string and wait for the fix.
Starting from 2.2.50 public release the issue is fixed.

How do I use application settings to store MySQL database connection info?

I'm creating an in-house application and have always hardcoded the database connection string. However, this time I want to do something different and give the users the ability to enter the information from the application.
I figured out that I can store the variables in the Application Settings and call them from code, but I can't figure out how to call them within the connection string.
Here's the code:
Dim dbConn As New MySqlConnection
dbConn.ConnectionString = "Server=172.43.96.271;Port=3306;Uid=someone;
Password=theirpassword;Database=thedb"
Hope I explained myself well?
You can simply concatenate the string together, or better yet, use the String.Format method:
dbConn.ConnectionString = String.Format("Server={0};Port={1};Uid={2};Password={3};Database={4}", My.Settings.Server, My.Settings.Port, My.Settings.Uid, My.Settings.Database)
If you were using MS SQL, I'd recommend using the SqlConnectionStringBuilder class to do it, but since you're using MySql, it doesn't really apply. You may be able to use it anyway, though.
You would have to use User Settings for this.
And, if you want the users to input the separate parts of the connection string (Server, Post, Username, Password and DB), you would have to create a settings entry for each of those, and then construct the connection string from those values.
Here's a good article for this: User Settings Applied

Question about build.properties

I'm writing a program that uses JDBC and connects to a database and does some edits / deletes. I need to put the URL, username, and password fields into a build.properties file, but I'm not sure how this would look or how to really get this to work.
(I'm completely new to this and haven't found any resources related to this specifically)
For example, in my code I have something like this :
String username = "something"
String password = "something"
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:#(DESCRIPTION=(ENABLE=BROKEN)" + "(FAILOVER=ON)(LOAD_BALANCE=ON)(ADDRESS=(PROTOCOL=TCP) ... etc", username, password);
and I want to put this in build.properties and for my code to create the connection using these properties instead of how I'm doing it now.
Any help would be appreciated!
Something like this:
First, create database.properties:
database.url = jdbc:mysql://host:port/database
database.driver = com.mysql.jdbc.Driver
database.username = username
database.password = password
Second, put the database.properties in your CLASSPATH.
Code looks something like this:
InputStream is = this.getClass().getClassLoader().getResourceAsStream("database.properties");
Properties dbProperties = Properties.load(is);
Class.forName(dbProperties.getProperty("database.driver"));
Connection connection = DriverManager.createConnection(dbProperties.getProperty("database.url"));
I didn't compile it, and I'm not sure if the syntax is 100% correct, but this illustrates the main idea.

SessionFactory - one factory for multiple databases

We have a situation where we have multiple databases with identical schema, but different data in each. We're creating a single session factory to handle this.
The problem is that we don't know which database we'll connect to until runtime, when we can provide that. But on startup to get the factory build, we need to connect to a database with that schema. We currently do this by creating the schema in an known location and using that, but we'd like to remove that requirement.
I haven't been able to find a way to create the session factory without specifying a connection. We don't expect to be able to use the OpenSession method with no parameters, and that's ok.
Any ideas?
Thanks
Andy
Either implement your own IConnectionProvider or pass your own connection to ISessionFactory.OpenSession(IDbConnection) (but read the method's comments about connection tracking)
The solution we came up with was to create a class which manages this for us. The class can use some information in the method call to do some routing logic to figure out where the database is, and then call OpenSession passing the connection string.
You could also use the great NuGet package from brady gaster for this. I made my own implementation from his NHQS package and it works very well.
You can find it here:
http://www.bradygaster.com/Tags/nhqs
good luck!
Came across this and thought Id add my solution for future readers which is basically what Mauricio Scheffer has suggested which encapsulates the 'switching' of CS and provides single point of management (I like this better than having to pass into each session call, less to 'miss' and go wrong).
I obtain the connecitonstring during authentication of the client and set on the context then, using the following IConnectinProvider implementation, set that value for the CS whenever a session is opened:
/// <summary>
/// Provides ability to switch connection strings of an NHibernate Session Factory (use same factory for multiple, dynamically specified, database connections)
/// </summary>
public class DynamicDriverConnectionProvider : DriverConnectionProvider, IConnectionProvider
{
protected override string ConnectionString
{
get
{
var cxnObj = IsWebContext ?
HttpContext.Current.Items["RequestConnectionString"]:
System.Runtime.Remoting.Messaging.CallContext.GetData("RequestConnectionString");
if (cxnObj != null)
return cxnObj.ToString();
//catch on app startup when there is not request connection string yet set
return base.ConnectionString;
}
}
private static bool IsWebContext
{
get { return (HttpContext.Current != null); }
}
}
Then wire it in during NHConfig:
var configuration = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2005
.Provider<DynamicDriverConnectionProvider>() //Like so

SQL Server 2005 Connection Question

In SQL Server 2005, is there a way to specify more than one connection string from within a .NET Application, with one being a primary preferred connection, but if not available it defaults to trying the other connection (which may be going to a diff DB / server etc)?
If nothing along those exact lines, is there anything we can use, without resorting to writing some kind of round-robin code to check connections?
Thanks.
We would typically use composition on our SqlConnection objects to check for this. All data access is done via backend classes, and we specify multiple servers within the web/app.config. (Forgive any errors, I am actually writing this out by hand)
It would look something like this:
class MyComponent
{
private SqlConnection connection;
....
public void CheckServers()
{
// Cycle through servers in configuration files, finding one that is usable
// When one is found assign the connection string to the SqlConnection
// a simple but resource intensive way of checking for connectivity, is by attempting to run
// a small query and checking the return value
}
public void Open()
{
connection.Open();
}
public ConnectionState State
{
get {return connection.State;}
set {connection.State = value;}
}
// Use this method to return the selected connection string
public string SelectedConnectionString
{
get { return connection.ConnectionString; }
}
//and so on
}
This example includes no error checking or error logging, make sure you add that, so the object can optionally report which connections failed and why.
Assuming that you'd want to access the same set of data, then you'd use clustering or mirroring to provide high availability.
SQLNCLI provider supports SQL Server database mirroring
Provider=SQLNCLI;Data Source=myServer;Failover Partner=myMirrorServer
Clustering just uses the virtual SQL instance name.
Otherwise, I can't quite grasp why you'd want to do this...
Unfortunately there are no FCL methods that do this - you will need to implement this yourself.