I recently deployed a small ASP.NET app on third party hosting using the Firebird embedded server (and .NET Data Provider), and encountered the error that you have described.
My present belief is that the problem is caused by the fact that the Firebird embedded server assumes that the embedded server library (fbembed.dll) will be in the application startup folder. Since this is an ASP.NET application, the application that is actually
running is aspnet_wp.exe, and so the application startup folder in which the data provider looks for the server DLL is the folder from which aspnet_wp.exe was started, not the folder in which your application's own main assembly is located.
The problem, of course, is that for third party hosting the folder from which aspnet_wp.exe is run is not usually accessible to a hosted account, and so there is no way to place a copy of fbembed.dll there other than to ask the hosting service to do it for
you, and they may have security issues with running a DLL that is not known to them in a common folder, or be otherwise unresponsive to your request.
My own workaround for this involves a bit of a kluge; I simply change the current directory in my application code just prior to opening any connection to the database. As it happens, this allows the fbembed DLL to be loaded when the connection is being opened.
This was discovered emprically, through trial and error; I have not seen any documentation of this as a feature.
Once loaded, by the way, the DLL normally stays in memory, and at that point the current directory could be anything you like so long as the DLL is not unloaded and re-loaded. Since I don't really know whether aspnet_wp.exe would take exception (no play on
words intended) to leaving the current folder changed, I am presently setting it back after each call to Open(). This has created no problems thus far; however, it may be that leaving it set to the location of the DLL, at least while you are performing database
accesses, would be equally safe, or safer. Or, it may be that problems will develop using either or both approaches down the road as the load factor increases, but so far, so good. Please post your results if you have experimented with this.
//I am hoping that Firebird only looks in the bin folder to find its
// DLL if that is not loaded, and once found, it does not need to be
// running from the bin folder any more (even though the connection
// remains open).
if((sOriginalDirectory != null)&& (sOriginalDirectory.Length > 0))
{
Directory.SetCurrentDirectory(sOriginalDirectory);
}
}
There are a number of other minor issues with using Firebird rather than SQL Server, all surmountable thus far.
In building the abovementioned application, I ported a set of data access classes designed for SQL Server to Firebird. Briefly, here are a few issues encountered:
* The Firebird .NET data provider does not seem to support the DBConcurrencyException, documentation notwithstanding. This seems to be due to a limitation in Firebird itself (the number of rows affected by an update or delete cannot be returned via a query,
although it is available from within a stored procedure). My own solution was to throw a custom exception from within each stored procedure when the number of rows affected is 0, and then trap this centrally in the application's data access classes, re-throwing
it as a DBConcurrencyException.
* Generating typed datasets must be done in your own program code, as there is no automated support for this. Here is some sample code that generates these from a DataSet that has been populated by reading rows from the database's member tables the correspond
to each of the DataSet's own internal tables. This can be part of a console application that is run during development each time your database schemata change:
StreamWriter tw = new StreamWriter(new FileStream(sPathToFileToHoldWrapperClassSourceCode,
FileMode.Create,
FileAccess.Write));
CodeNamespace cn = new CodeNamespace(sDataSetWrapperClassNamespace);
CSharpCodeProvider cs = new CSharpCodeProvider();
ICodeGenerator cg = cs.CreateGenerator();
* Only one process can access the database file at a time when using the embedded server. For an ASP.NET application, that one process will normally be aspnet_wp.exe. The multiple threads created for each browser request seem to have no problem sharing the
database; although access is restricted to one process, I am not aware of any limit on the number of concurrent threads. While this works great for Web sites, if you have any reporting or other software that wants to access the database while your Web site
is operational, you may be out of luck. For such software, or if you want to back up, it will probably be necessary to briefly stop the ASP.NET process while the .FDB file is copied. For backup, you would want to do this anyway to ensure that the database
is in a consistent state when it is backed up. While I haven't tried this, it may be that any reporting or other tools that you write using ASP.NET would be able to run concurrently without difficulty, even if they are part of a separate ASP.NET application
(so long as they are sharing the same instance of aspnet_wp.exe). If someone tries this and can confirm or deny it, I'd be interested in knowing the result.
* This is probably obvious, but if you place your database file inside your bin folder, then each time it changes it will reset the ASP.NET process, causing your Session state to be dumped, as well as other undesirable phenomena. So, of course you must put
it in its own folder and specify the path to this folder in the connection string. This means separate connection strings for your development and production environments.
Other than the above, nothing major comes to mind, although of course there are numerous minor differences in stored procedure syntax, SQL syntax, etc. The data provider also seems quite solid so far, as well. IMHO, Firebird *is* the proverbial free lunch
that has been dropped unexpectedly in front of developers by Borland and the open source community. It would not surprise me to learn that Borland made Interbase available to the open source community in the hope of undermining one of their competitors' major
revenue streams and in generally stopping things from getting locked too tightly to the Windows platform (e.g., a Windows .NET application using Firebird can be more easily ported to a Mono application runing under Linux). While that is pure and uninformed
speculation, is does provide one possible explanation for why we have had this free, stable and unrestricted asset placed before us on a silver platter. That, and of course the dedicated denizens of the open source projects that created it its present form.
Well, I am new to Firebird, so I may have all of this political stuff all wrong, but that's my present working hypothesis.
This claims that the best way to deal with the problem is to change the .NET provider source to look in your application's own folder and then re-build it.
That would be a less klugy alternative to the approach that I have taken. Also, to me this implies that the .NET provider might eventually incorporate this as a feature (e.g., a connection string parameter that allows you to specify where to find fbembed.dll.
I have actually suggested this in the past but so far do not have a response).
There is another interesting comment on the same page regarding ASP.NET restarts, which occur by default I think every 5,000 requests or so. The problem is that the restarts overlap to provide uninterrupted service, so that during the transition there are
actually two ASPNET processes running at once.
The author seems to think that the database file would remain locked by the first ASPNET process until that process was terminated, but unless I miss my guess (help me out here if this is wrong), it would only remain locked so long as that process was maintaining
an open connection.
Even so, since the first ASPNET instance has the ability to lock the FDB file at any time before it is terminated, the second one will not be able to access it if the first one is using it, and vice versa. This means that some of your requests might be refused
during the period of transition. I would guess that this period would last until the last request (to your application) that is in progress for the old ASPNET instance is satisfied, which probably wouldn't be much longer than it takes to load the most demanding
page of your application.
The author of this comment is more or less negative about using Firebird's embedded server due to this restart problem, but so far I have decided not to be discouraged. If you have turned pooled connections off (as you must for this to work practically), and
close your open connections as soon as you are finished with them, then even though the processes are overlapping in time, the possibility that both will simultaneously want to have a connection *open* should be reduced even further. Some simple try/catch/re-try
code around your Open() statements could bulletproof you against this remaining risk somewhat, possibly reducing the problem to a long page load every so often.
Caveat: I haven't proven the above; it is speculation. But the advantages of using embedded Firebird on shared hosting seem so significant that it seems worth working through these little problems until and if something truly insurmountable arises.
Thank you for taking the time to report on your finings on this issue. We should have the DotNetNuke Firebird provider ready for BETA in January, We plan to release the normal Firebird server version then fix this embeded issue, your research will be very helpful.
Personally I think we will see: A) How much demand there is for the embeded version B) How many hosts refuse to instal the files needed. I think that there will be a lot of people who start sites using SQL server Express then realize that for a more powerful
site they have to pay big bucks for SQL server. Then they will see that Firebird provides unlimited growth for free.
I found another way to run embedded firebird in a ASP.NET application.
I'm running this on a brinkster account. I asked brinkster, and they didn't want to place the fbembed.dll in the system32 so i tried the workaround on this page :
I think that you will only have this option for a little while longer. Personally I would not want to run embedded on a shared server. Think about this. If you can run an arbitrary piece of unmanaged code on that machine, then so can every other website.
Your site security is severely compromised. Calling unmanaged code is not allowed in anything but Full trust, which is not a secure environment for running a public website.
I am far from being an expert on shared hosting, but my understanding is that they rely upon OS features that exclude users from writing into one another's disk and process space, which would not require a managed code only policy to work. If problems develop
nonetheless due to a specific account's actions, the remedy is generally to identify and terminate that account. I have personally never encountered a managed code only policy in a hosting service's usage agreement.
Here is the relevant section from my own hosting service's usage policy:
"[We do not] allow more than 20% of system or network resources to be in use by any one website for any length of time. Any website that poses security threats or adverse effects on any other [of our] users is subject to immediate termination. When appropriate
compliance has been deemed by [us], the website may be reconnected without any fees or charges."
So, this allows me to invoke unmanaged code from my Web and other hosted applications, but it's my responsibility to make sure the code is OK, and if I mess up, they'll get me.
Microsoft is strongly pushing that all shared hosting providers operate in medium trust which does not provide access to unmanaged code. Now either Microsoft has some inside information on how .Net and IIS work and is making a sound security recomendation,
or Microsoft, being the security conscious company that they are is taking an extremely conservative approach to security. Given Microsoft's history with security, I do not put much stock in Microsoft being overly cautious when it comes to security.
Anyone with a strong security background will tell you that security should always be applied in layers. Each layer protects against different kinds of threats and makes the hackers job more difficult. If you allow websites to operate at full trust, including
access to unmanaged code, then you have effectively disabled all Code Access Security and are now relying strictly on OS security. With that being the case, you have completely removed any security provided by .Net. Microsoft is not the only ones recommending
against running at full trust. Every security company I have seen recommends the same thing.
So you may continue to believe that it is ok, but the tide is already turning in the hosting community and it won't be long before almost all hosters start restricting accounts. You have been warned.
Well, you make some good points. One view would be that if you want tight security, go for dedicated hosting. I would guess that most applications that run on shared hosting are less concerned about security than are those that run on dedicated hosting.
The ASP.NET/Firebird application that Goalstate just deployed, for example (http://citizenlobbyist.net) handles nothing more than data defining some dynamically-created public Web pages and some e-mail addresses supplied by the owners of, and visitors to, those
sites. Goalstate's other application there is a SQL Server-based system for online editing and display of radio station program guides, also not very private and not very sensitive. Other than these, there is just Goalstate's own Web site. If Goalstate
has a need to collect credit card data in the future, it will probably use the Paypal ASP.NET controls or some other third-party solution. So, an intruder on the shared server would get little more than a few e-mail addresses and some dotfuscated assemblies.
Hosting services will have to balance server security with the needs of their customers and come up with some kind of compromise. Ultimately, what hosting customers want in the way of services, and are willing to tolerate in the way of security vulnerabilities,
will probably determine the way this is decided.
I wouldn't hold my breathe on the embedded mode. As indicated by the
FirebirdDotNet team, it was not designed to work in a multi-process environment and therefore would impose serious restrictions on using it in an ASP.Net environment. I can think of few scenarios where you have enough control to overcome the application
recycling problem, yet don't have enough control to install the full FireBird dbms. The one environment where an embedded db would provide real benefit(shared hosting) is the one place where it is extremely unlikely that they would turn off Overlapped Worker
Process mode.
Goalstate
Member
20 Points
4 Posts
Re: Firebird Provider
Nov 29, 2005 10:07 PM|LINK
I recently deployed a small ASP.NET app on third party hosting using the Firebird embedded server (and .NET Data Provider), and encountered the error that you have described.
My present belief is that the problem is caused by the fact that the Firebird embedded server assumes that the embedded server library (fbembed.dll) will be in the application startup folder. Since this is an ASP.NET application, the application that is actually running is aspnet_wp.exe, and so the application startup folder in which the data provider looks for the server DLL is the folder from which aspnet_wp.exe was started, not the folder in which your application's own main assembly is located.
The problem, of course, is that for third party hosting the folder from which aspnet_wp.exe is run is not usually accessible to a hosted account, and so there is no way to place a copy of fbembed.dll there other than to ask the hosting service to do it for you, and they may have security issues with running a DLL that is not known to them in a common folder, or be otherwise unresponsive to your request.
My own workaround for this involves a bit of a kluge; I simply change the current directory in my application code just prior to opening any connection to the database. As it happens, this allows the fbembed DLL to be loaded when the connection is being opened. This was discovered emprically, through trial and error; I have not seen any documentation of this as a feature.
Once loaded, by the way, the DLL normally stays in memory, and at that point the current directory could be anything you like so long as the DLL is not unloaded and re-loaded. Since I don't really know whether aspnet_wp.exe would take exception (no play on words intended) to leaving the current folder changed, I am presently setting it back after each call to Open(). This has created no problems thus far; however, it may be that leaving it set to the location of the DLL, at least while you are performing database accesses, would be equally safe, or safer. Or, it may be that problems will develop using either or both approaches down the road as the load factor increases, but so far, so good. Please post your results if you have experimented with this.
In case it is not obvious, here is the code:
protected void OpenConnectionInAppBinDirectory()
{
string sOriginalDirectory = Directory.GetCurrentDirectory();
string sApplicationBinPath = (string) GlobalValues.MainApplicationBinFolder;
Directory.SetCurrentDirectory(sApplicationBinPath);
this.connection.Open();
//I am hoping that Firebird only looks in the bin folder to find its
// DLL if that is not loaded, and once found, it does not need to be
// running from the bin folder any more (even though the connection
// remains open).
if((sOriginalDirectory != null)&& (sOriginalDirectory.Length > 0))
{
Directory.SetCurrentDirectory(sOriginalDirectory);
}
}
There are a number of other minor issues with using Firebird rather than SQL Server, all surmountable thus far.
In building the abovementioned application, I ported a set of data access classes designed for SQL Server to Firebird. Briefly, here are a few issues encountered:
* The Firebird .NET data provider does not seem to support the DBConcurrencyException, documentation notwithstanding. This seems to be due to a limitation in Firebird itself (the number of rows affected by an update or delete cannot be returned via a query, although it is available from within a stored procedure). My own solution was to throw a custom exception from within each stored procedure when the number of rows affected is 0, and then trap this centrally in the application's data access classes, re-throwing it as a DBConcurrencyException.
* Generating typed datasets must be done in your own program code, as there is no automated support for this. Here is some sample code that generates these from a DataSet that has been populated by reading rows from the database's member tables the correspond to each of the DataSet's own internal tables. This can be part of a console application that is run during development each time your database schemata change:
StreamWriter tw = new StreamWriter(new FileStream(sPathToFileToHoldWrapperClassSourceCode,
FileMode.Create,
FileAccess.Write));
CodeNamespace cn = new CodeNamespace(sDataSetWrapperClassNamespace);
CSharpCodeProvider cs = new CSharpCodeProvider();
ICodeGenerator cg = cs.CreateGenerator();
TypedDataSetGenerator.Generate(ds, cn, cg);
cg.GenerateCodeFromNamespace(cn, tw, null);
tw.Flush();
tw.Close();
ds.WriteXmlSchema(sPathToXsdFileToHoldDescriptionOfDataTableColumns);
* Only one process can access the database file at a time when using the embedded server. For an ASP.NET application, that one process will normally be aspnet_wp.exe. The multiple threads created for each browser request seem to have no problem sharing the database; although access is restricted to one process, I am not aware of any limit on the number of concurrent threads. While this works great for Web sites, if you have any reporting or other software that wants to access the database while your Web site is operational, you may be out of luck. For such software, or if you want to back up, it will probably be necessary to briefly stop the ASP.NET process while the .FDB file is copied. For backup, you would want to do this anyway to ensure that the database is in a consistent state when it is backed up. While I haven't tried this, it may be that any reporting or other tools that you write using ASP.NET would be able to run concurrently without difficulty, even if they are part of a separate ASP.NET application (so long as they are sharing the same instance of aspnet_wp.exe). If someone tries this and can confirm or deny it, I'd be interested in knowing the result.
* This is probably obvious, but if you place your database file inside your bin folder, then each time it changes it will reset the ASP.NET process, causing your Session state to be dumped, as well as other undesirable phenomena. So, of course you must put it in its own folder and specify the path to this folder in the connection string. This means separate connection strings for your development and production environments.
Other than the above, nothing major comes to mind, although of course there are numerous minor differences in stored procedure syntax, SQL syntax, etc. The data provider also seems quite solid so far, as well. IMHO, Firebird *is* the proverbial free lunch that has been dropped unexpectedly in front of developers by Borland and the open source community. It would not surprise me to learn that Borland made Interbase available to the open source community in the hope of undermining one of their competitors' major revenue streams and in generally stopping things from getting locked too tightly to the Windows platform (e.g., a Windows .NET application using Firebird can be more easily ported to a Mono application runing under Linux). While that is pure and uninformed speculation, is does provide one possible explanation for why we have had this free, stable and unrestricted asset placed before us on a silver platter. That, and of course the dedicated denizens of the open source projects that created it its present form. Well, I am new to Firebird, so I may have all of this political stuff all wrong, but that's my present working hypothesis.
Carl
Goalstate
Member
20 Points
4 Posts
Re: Firebird Provider
Nov 29, 2005 10:52 PM|LINK
I followed your link and there was another link there to this page:
http://www.dotnetfirebird.org/blog/2005/11/how-to-use-embedded-firebird-in-aspnet.html
This claims that the best way to deal with the problem is to change the .NET provider source to look in your application's own folder and then re-build it.
That would be a less klugy alternative to the approach that I have taken. Also, to me this implies that the .NET provider might eventually incorporate this as a feature (e.g., a connection string parameter that allows you to specify where to find fbembed.dll. I have actually suggested this in the past but so far do not have a response).
There is another interesting comment on the same page regarding ASP.NET restarts, which occur by default I think every 5,000 requests or so. The problem is that the restarts overlap to provide uninterrupted service, so that during the transition there are actually two ASPNET processes running at once.
The author seems to think that the database file would remain locked by the first ASPNET process until that process was terminated, but unless I miss my guess (help me out here if this is wrong), it would only remain locked so long as that process was maintaining an open connection.
Even so, since the first ASPNET instance has the ability to lock the FDB file at any time before it is terminated, the second one will not be able to access it if the first one is using it, and vice versa. This means that some of your requests might be refused during the period of transition. I would guess that this period would last until the last request (to your application) that is in progress for the old ASPNET instance is satisfied, which probably wouldn't be much longer than it takes to load the most demanding page of your application.
The author of this comment is more or less negative about using Firebird's embedded server due to this restart problem, but so far I have decided not to be discouraged. If you have turned pooled connections off (as you must for this to work practically), and close your open connections as soon as you are finished with them, then even though the processes are overlapping in time, the possibility that both will simultaneously want to have a connection *open* should be reduced even further. Some simple try/catch/re-try code around your Open() statements could bulletproof you against this remaining risk somewhat, possibly reducing the problem to a long page load every so often.
Caveat: I haven't proven the above; it is speculation. But the advantages of using embedded Firebird on shared hosting seem so significant that it seems worth working through these little problems until and if something truly insurmountable arises.
Carl
adefwebserve...
Contributor
5912 Points
1207 Posts
MVP
Re: Firebird Provider
Nov 29, 2005 11:13 PM|LINK
Open Light Group
LightSwitchHelpWebsite.com | ADefWebserver.com
dawoe
Member
335 Points
69 Posts
Re: Firebird Provider
Nov 30, 2005 09:06 AM|LINK
I found another way to run embedded firebird in a ASP.NET application.
I'm running this on a brinkster account. I asked brinkster, and they didn't want to place the fbembed.dll in the system32 so i tried the workaround on this page :
http://www.balconsulting.net/DasBlog/PermaLink,guid,a50036b2-cf16-4467-a284-3380e7a77c12.aspx
Here is the code in VB for those who want to try it.
<DllImport("KERNEL32.DLL")> _
Public Shared Function LoadLibraryA(ByVal lpLibFileName As String) As Integer
End Function
<DllImport("KERNEL32.DLL")> _
Public Shared Function FreeLibrary(ByVal hLibModule As Integer) As Integer
End Function
Dim lnHandle As Integer = LoadLibraryA(LoadLibraryA(Server.MapPath("~/bin") + "\fbembed.dll")
'Put your DB-code here
FreeLibrary(lnHandle)
By the way, you have to import System.Runtime.InteropServices and the folder where you place the fbembed.dll needs modify permissions
You can see it in action here on a brinkster account. I did a SELECT * FROM PHONE_LIST on the EMPLOYEE sample db
jbrinkman
Star
9822 Points
1963 Posts
Re: Firebird Provider
Nov 30, 2005 11:25 AM|LINK
Goalstate
Member
20 Points
4 Posts
Re: Firebird Provider
Nov 30, 2005 08:25 PM|LINK
Here is the relevant section from my own hosting service's usage policy:
"[We do not] allow more than 20% of system or network resources to be in use by any one website for any length of time. Any website that poses security threats or adverse effects on any other [of our] users is subject to immediate termination. When appropriate compliance has been deemed by [us], the website may be reconnected without any fees or charges."
So, this allows me to invoke unmanaged code from my Web and other hosted applications, but it's my responsibility to make sure the code is OK, and if I mess up, they'll get me.
Carl
jbrinkman
Star
9822 Points
1963 Posts
Re: Firebird Provider
Dec 01, 2005 03:18 AM|LINK
Microsoft is strongly pushing that all shared hosting providers operate in medium trust which does not provide access to unmanaged code. Now either Microsoft has some inside information on how .Net and IIS work and is making a sound security recomendation, or Microsoft, being the security conscious company that they are is taking an extremely conservative approach to security. Given Microsoft's history with security, I do not put much stock in Microsoft being overly cautious when it comes to security.
Anyone with a strong security background will tell you that security should always be applied in layers. Each layer protects against different kinds of threats and makes the hackers job more difficult. If you allow websites to operate at full trust, including access to unmanaged code, then you have effectively disabled all Code Access Security and are now relying strictly on OS security. With that being the case, you have completely removed any security provided by .Net. Microsoft is not the only ones recommending against running at full trust. Every security company I have seen recommends the same thing.
So you may continue to believe that it is ok, but the tide is already turning in the hosting community and it won't be long before almost all hosters start restricting accounts. You have been warned.
Goalstate
Member
20 Points
4 Posts
Re: Firebird Provider
Dec 01, 2005 08:08 PM|LINK
The ASP.NET/Firebird application that Goalstate just deployed, for example (http://citizenlobbyist.net) handles nothing more than data defining some dynamically-created public Web pages and some e-mail addresses supplied by the owners of, and visitors to, those sites. Goalstate's other application there is a SQL Server-based system for online editing and display of radio station program guides, also not very private and not very sensitive. Other than these, there is just Goalstate's own Web site. If Goalstate has a need to collect credit card data in the future, it will probably use the Paypal ASP.NET controls or some other third-party solution. So, an intruder on the shared server would get little more than a few e-mail addresses and some dotfuscated assemblies.
Hosting services will have to balance server security with the needs of their customers and come up with some kind of compromise. Ultimately, what hosting customers want in the way of services, and are willing to tolerate in the way of security vulnerabilities, will probably determine the way this is decided.
Carl
ebradley4
Member
160 Points
32 Posts
Re: Firebird Provider
Feb 01, 2006 05:58 PM|LINK
I see from the project web site that the vast majority of the stored procs have been converted--good work--thank you!
Has any progress been made on getting the embedded mode to work? Is there an official release coming soon?
Thanks for any new information and thanks for you work on this.
jbrinkman
Star
9822 Points
1963 Posts
Re: Firebird Provider
Feb 01, 2006 09:46 PM|LINK