ASP.NET: How to support two database types in one application? (Access, MS SQL Server 2008 Express) - asp.net

The ASP.NET web application I am developing needs to support two different types of databases, namely Access and MS SQL Server 2008 Express.
I already have connection strings for each database type stored in web.config, and I have another web.config value that specifies which one to use. So I can get the proper connection string with no problem.
The big problem comes with the database objects. For Access, which I have already implemented, I am using the objects OleDbConnection, OleDbCommand and OleDbDataReader in the code to make the database calls.
It appears that for SQL Server, I can't use those objects, but rather I would need to use the objects SqlConnection, SqlCommand and SqlDataReader to do essentially the same things.
I want to reuse as much of my current code as possible and not have to create two separate blocks for each database type. (I have a lot of methods that take an OleDbDataReader as a parameter - I do not want to have to make 2 of each of those methods, for example.)
I noticed that the connection objects both inherit from DbConnection. And the same is true for the data readers (DbDataReader) and the commands (DbCommand).
Would it be possible to take my existing code for Access, replace all of the Ole objects with the Db objects, and then cast those objects as the proper type depending on the current database type?
Are there any best practices for supporting two database types in one ASP.NET application?
I can add some of my code if that would help. Thanks.

Yes, from framework 2.0 all data readers inherit from the DbDataReader class, so your methods could take a DbDataReader isntead of an OleDbDataReader, and you could use the methods with any database.
However, the databases have different dialects of SQL, so you either have to stay on a narrow path of features that work in all databases that you use, or have separate queries for some tasks.
A specific example of differences is that Access uses data literals like #2010-09-24# while SQL Server uses date literals like '2010-09-24'. Generally most that has to do with dates differs.

The link you're likely missing is the functionality of the DbProviderFactories class. Using this class (and associated helpers also in System.Data.Common), you can abstract the provider and use references to the base classes (such as DbConnection and DbCommand) to do the work. It'd look something like this:
private void DoSomething(string provider, string connectionString, string something)
{
DbProviderFactory factory = DbProviderFactories.GetFactory(provider);
DbConnection connection = factory.CreateConnection();
connection.ConnectionString = connectionString;
DbCommand command = connection.CreateCommand();
command.CommandText = something;
DbDataReader reader = command.ExecuteReader();
//etc...
}
The provider name is a bit tricky to acquire, but should be the invariant class name that matches one of those returned by DbProviderFactories.GetFactoryClasses(). Or, you can simply hard code them. They don't change much, but it is a magic string embedded in your code and may cause issues eventually.
Additional features can be accessed through factory.CreateCommandBuilder that can help you traverse the differences in how the providers handle things like parameters and such.

Related

How or where to remove generated SQL from tableadapter code?

I've been developing an app which uses strongly typed datasets and stored procedures. I've just graduated and this was the method that was sold to us as the way to go. I'm starting to have severe doubts.
My client has advised me that he might change from SQL Server to MySQL. From what I've read it might be better to not use stored procedures as migrating could become more difficult. So anyhow I've just implemented a new table adapter query using the wizard and selected Use SQL Statements rather than Create new stored procedure.
My call to the query
Intranet.administratorsDataTable dt = taAdministrators.GetAdministrators();
now generates this error:
executereader requires an open and available connection. the
connection's current state is closed
I have no idea why this auto generated code doesn't have a connection and I'm hungover and in no shape to deal with this. I decided to just go back to the SP's for the moment so I can get some work done. This error is still being thrown (same table adapter, same method name but reconfigured to use a SP). All of my other DB calls work fine.
I'm assuming the generated SQL code is still floating around somewhere even though I changed the adapter to use SP's. Can someone tell me where it is so I can delete it?
On another note I'm really starting to think that using SqlConnection and SqlCommand manually is a much better option, as using these query 'Tools' are just way to much trouble when it comes to flexibility such as modifying database tables etc. Can any of you more experienced people tell me if that's correct or do you advocate using table adapters?
*Edit
it also throws these:
Invalid operation. The connection is closed.
and
There is already an open DataReader associated with this Command which must be closed first.
The solution was to go to the query properties in the tableAdapter and manually change the "Command Type" to StoredProcedure.
highlight the query > go to properties window > change the command type
Seem this didn't (or doesn't) get auto updated when I reconfigure the query.
if you provide some code, it would be better.
I think, you need to open the the connection.
SqlCommand Cmd= new SqlCommand();
Cmd.Open();
// then u can use Cmd.ExecuteReader();

is static methods secure in asp.net

heys guys,
i have a website, which contains lots of db work to display data on page, so i have created a VB class which is public, under App_Code.
Now i have all the methods and functions under that class are Shared(Static), also i have a connection variable which is also static.
Client complains, that sometime there appears an error on the page, one of those error is Field Name does not belong to table Table, i dont understand, about this, as this is very rare, if there is no field with name, then this should occur everytime, one of my colleague says that there should not be Shared methods or functions... is this correct..
There is no "security" problem with a static method. Your colleague is confused. Whether or not the code you wrote should be static or instance methods depends on what exactly it does. But having them as static methods is not "dangerous."
I suggest you track down the query that is causing the problem because the method being static is certainly not the issue.
As far as your connection goes, I would not recommend keeping it as a static variable. I assume this is a SqlConnection, or something similar. In that case, if you keep it as a static variable, it is possible for the following to occur:
Your connection is never closed, even after you're done using it.
You will have issues if you have multiple queries trying to use the connection at the same time.
So I recommend you use the following pattern to ensure your connections are only kept open as long as they are in use.
public void DoSomething()
{
//Doing some work that doesn't need a connection.
//Now ready to submit or fetch data from the database.
using (SqlConnection connection = new SqlConnection(...))
{
using (SqlCommand command = new SqlCommand(..., connection))
{
//Now, working with the connection and command.
}
}
//Done with the connection, doing more work now.
}
The using statement works with anything that is IDisposable. Your connection variable here will be automatically closed and destroyed at the closing bracket of the using statement. I recommend you use it for anything that you can. Streams, SqlConnections, Fonts, etc.
It sounds to me like you have a infrequently-used SQL statement that refers to a column that does not exist on a table.
For example - suppose you had SQL like so
SELECT Col4 FROM Table2
and Col4 was not a member of Table2. You would get the error you describe.
If you're building SQL dynamically (which is dodgey) you might run into this.
But I don't think it has anything to do with your method 'security.'

Entity Framework to multiple databases (same schema) at runtime?

First of all, let me state I'm very new to EF. With that said, here's my dilemma:
There will be an ASP.NET App migrated to ASP.NET MVC. I would like to utilize EF for this. There is one main database which stores "client information". Apart from that, every "client" has their own database. These are the constraints we have.
Currently, client information in the main DB that enables me to build a connection string per client and make individual SQL calls.
How would I accomplish the same thing in Entity Framework? Each database WILL have the same schema. Is there a way to programmatically switch the Connection String? These DBs are currently on the same server, but that's not a requirement and it may be a completely different server.
Any ideas?
Multiple connection strings in the Web.config would be a last resort. Even then, I'm not sure how exactly to wire this up.
Thank you in advance.
If you work through an EntityConnection in the constructor of your entities object, you can change the database pretty easily.
EntityConnection con = new EntityConnection(connString);
con.ChangeDatabase(dbName);
using (Entities context = new Entities(con))
{
// Some code here
}
When you build a data context, here's how to programmatically change the connection string at runtime by modifying the Context.Connection property:
//Get the connection string from app.config and assign it to sqlconnection string builder
SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder(((EntityConnection)context.Connection).StoreConnection.ConnectionString);
sb.IntegratedSecurity = false;
sb.UserID ="User1";
sb.Password = "Password1";
//set the object context connection string back from string builder. This will assign modified connection string.
((EntityConnection)context.Connection).StoreConnection.ConnectionString = sb.ConnectionString;
Taken from: http://sivapinnaka.spaces.live.com/blog/cns!B027EF7E7070AD69!211.entry
If the number of your customers is limited and the connection strings hardly ever change, an elegant way might be to use ConfigurationManager.ConnectionStrings to retreive the connection string needed.
Like
string connectionString = ConfigurationManager.ConnectionStrings["Miller"].ConnectionString;
return new Entities(connectionString);
See also
http://msdn.microsoft.com/en-us/library/ms254494.aspx

How to use SQL from asp.net?

Building a relatively simple website, and need to store some data in the database (mainly authentication, but there's some per-user stuff). I've worked on a couple of websites previously, and used database there too, but never liked the way I accessed the database.
The way I usually did this was by having a SqlMethods.cs, which basically was a static class with a whole lot of static methods such as bool CheckUserExistence(string username, string password) and SqlDataReader GetJobListings(int advertiserId), each of which was essentially "open connection, call a sproc, return what it returns". This approach seems un-natural to me, however. I cant quite put my mind to what I want it to look like, but this seems...weird.
So, my question is this: how do you access the database from your asp.net projects?
I am using SQL2005. I also dont think I'll need an ORM of any kind, since there really isnt that much to get from the DB, but maybe its easier with one? Suggest something.
Thanks!
Edit:I currently decided to just create a static class Sql that will have a number of sql-related methods (such as ExecuteReader(sprocName, params[]), etc) that will call the sproc with the given parameters and just return the DataReader.
Then, have classes for specific functionality, such as Authentication with methods like CheckUserExistence(username, password) and LogoffUser(session). These methods would just call Sql.ExecuteReader("sp_Auth_CheckUserExistence", _some_params_here_) and process the result as needed.
I don't know if thats good or bad, but it seems to work for me at the moment. Plus, I like the way it feels - its all nicely separated functionality-wise.
So, any more suggestions?
Check out Linq to SQL or Linq to Entities:
http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx
http://msdn.microsoft.com/en-us/library/bb386964.aspx
The simplest way to do it is to create a data access class for each table in your database. It should have private variables and public properties for all of the columns in the table and the methods you describe should fill the internal variables (or use them to update the database).
Public Class MyTable
Private _id As Integer
Private _Name as String
Public ReadOnly Property ID As Integer
' Regular stuff here
End Property
Public Property Name As String
' Regular stuff here
End Property
Public Sub Load()
' Call SQL and get a data reader.
' Set _id and _Name from the data reader.
End Sub
End Class
Then, in your other code:
Dim mt As New MyTable
mt.Load()
' Now use mt.ID and mt.Name to access the data

Linq to Sql - Set connection string dynamically based on environment variable

I need to set my connection string for Linq to Sql based on an environment variable. I have a function which will return the connection string from the web.config based on the environment variable, but how do I get Linq to always use this "dynamically created" connection string (preferably without having to specify it every time)?
I know I can specify the connection string using the constructor, but how does that work when using the datacontext in a LinqDataSource?
Use:
MyDataClassesDataContext db = new MyDataClassesDataContext(dynamicConnString);
For a LinqDataSource, intercept the ContextCreating event and create the DataContext manually as above:
protected void LinqDataSource_ContextCreating(object sender, LinqDataSourceContextEventArgs e)
{
e.ObjectInstance = new MyDataClassesDataContext (dynamicConnString);
}
From MSDN:
By default, the LinqDataSource control
creates an instance of the type that
is specified in the ContextTypeName
property. The LinqDataSource control
calls the default constructor of the
data context object to create an
instance of the object. It is possible
that you have to use a non-default
constructor or you have to create an
object that differs from the one
specified in the ContextTypeName
property. In that case, you must
handle the ContextCreating event and
manually create the data context
object.
Open up the LINQ to SQL designer, and open the Properties tab of the designer (the schema itself), expand Connection and set Application Settings to False. Save.
Close that down and open up your DataContext designer file (dbml_name.designer.cs) and alter the DataContext constructor. You will immediately notice how your connection string decided to jump in here as you turned off application wide settings. So the part to focus on here is altering the base() inheritor. Renaming ConnString” below to suit your own. I also noticed a DatabaseAttribute on the class which I don’t think plays a big part and has any implications on the connection settings. You will also need a reference to System.Configuration:
public dbDataContext() : base(ConfigurationManager.ConnectionStrings["MyConnString"].ConnectionString, mappingSource)
Open the App.config or Web.config featured in the project where your LINQ to SQL classes reside, and rename the connection string to what you defined as “MyConnString“.
You now must Cut the entire entry with name change and Paste it into either the App.config or Web.config of the application which is to access the data, such as a web application, Silverlight, WPF, WCF etc. It is important that you alter the configuration file of the calling application which is to access the data, as the ConfigurationManager defined in your LINQ to SQL classes will look for the .config file from where the calling application is executing from, no matter where your LINQ to SQL classes have been Defined. As you can see, it works a little differently from before.
Now Right Click and open the Properties on your DAL or project containing your LINQ to SQL classes and remove the connection string “Application Setting” reference on the Settings tab.
Rebuild. You’re all done, now just do a Find in Files check for perhaps your database name that you know was featured in the connection string to check for any stragglers, there shouldn’t be any.
The DataContext class has a constructor that takes in a connection string.
you can change the connection string dynamically if you will implement the OnCreated() function. This function is a partial function and it can be implemented in seperate file other than where you dbml exists.
for detail please see this article
http://aspilham.blogspot.com/2011/01/how-do-i-set-connection-string-in-linq.html

Resources