SQLite on Mono Shared Cache Mode? - sqlite

Does Mono.Data.SQLite support in-memory databases using Shared Cache Mode? I'm getting an ArgumentException complaining about the format of the data source URI string. The connection string I'm attempting to use is:
URI=file::memory:?cache=shared;Version=3
I've also tried with the Data Source connection string property, with similar results.
(For reference, this is in the context of an iPhone MonoTouch application.)

Related

Is it possible to combine .Net GZip compression and SQL Server compression?

For various reasons related to network bandwidth and performance we have an application with large Unicode strings converted to byte arrays compressed with the GZipStream .Net framework (.Net core 3.1) functionality.
We want to store these in a SQL Server 2017 varbinary(max) column for later retrieval and decompression - this works fine using the same GZipStream library to decompress.
We would also like to take advantage of the T-SQL Decompress function to be able to query the data on the DB server (without having to bring it all back into .Net and decompress it there)
Whilst Decompress does seem to work (as in it doesn't throw an error and it produces a binary output that can be cast to nvarchar(max)), the resulting nvarchar is totally different from the original source - it actually crashes SSMS when displayed!
This is not a problem if we pass the decompressed string into SQL Server and compress it there using the Compress function, but we do not want to do this because it requires additional decompress step and extra bandwidth consumption.
I have ensured we're on CU20 of SQL Server 2017, so I don't think it's a patching problem.
I have tried the using the different compression ratio options in the .Net library but they all produce the same problem.
It would appear that despite both being GZip compression that the T-SQL and .Net compression algorithms are not compatible, but if anyone has succeeded in combining the two, I would appreciate hearing how.
Arrgh... I was being an idiot! My source strings (they were XML) were in UTF-8 so this worked:
using (var compressStream = new MemoryStream())
using (var compressor = new GZipStream(compressStream, CompressionMode.Compress))
{
compressor.Write(Encoding.UTF8.GetBytes(largeString));
compressor.Close();
var bytesToWriteToSQLVarbinaryMax = compressStream.ToArray();
}
And then I could do:
SELECT Cast(Decompress(bytes) AS varchar(max)) FROM compressedTable

EntityException: The underlying provider failed on Open. Can one server closing a db connection, make another server fail on opening?

I am experiencing database connection errors with an ASP.NET application written in VB, running on three IIS servers. The underlying database is MS Access, which is on a shared network device. It uses Entity Framework, code first implementation and JetEntityFrameworkProvider.
The application is running stable. But, approximately 1 out of 1000 attempts to open the database connection fails with either one of the following two errors:
06:33:50 DbContext "Failed to open connection at 2/12/2020 6:33:50 AM +00:00 with error:
Cannot open database ''. It may not be a database that your application recognizes, or the file may be corrupt.
Or
14:04:39 DbContext "Failed to open connection at 2/13/2020 2:04:39 PM +00:00 with error:
Could not use ''; file already in use.
One second later, with refreshing (F5), the error is gone and it works again.
Details about the environment and used code.
Connection String
<add name="DbContext" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=x:\thedatabase.mdb;Jet OLEDB:Database Password=xx;OLE DB Services=-4;" providerName="JetEntityFrameworkProvider" />
DbContext management
The application uses public property to access DbContext. DbContext is kept in the HttpContext.Current.Items collection for the lifetime of the request, and is disposed at it’s end.
Public Shared ReadOnly Property Instance() As DbContext
Get
SyncLock obj
If Not HttpContext.Current.Items.Contains("DbContext") Then
HttpContext.Current.Items.Item("DbContext") = New DbContext()
End If
Return HttpContext.Current.Items.Item("DbContext")
End SyncLock
End Get
End Property
BasePage inits and disposes the DbContext.
Protected Overrides Sub OnInit(e As EventArgs)
MyBase.OnInit(e)
DbContext = Data.DbContext.Instance
...
End Sub
Protected Overrides Sub OnUnload(e As EventArgs)
MyBase.OnUnload(e)
If DbContext IsNot Nothing Then DbContext.Dispose()
End Sub
What I have tried
Many of the questions on SO which address above error messages, deal with generally not being able to establish a connection to the database – they can’t connect at all. That’s different with this case. Connection works 99,99% of the time.
Besides that, I have checked:
Permissions: Full access is granted for share where .mdb (database) and .ldb (locking file) resides.
Network connection: there are no connection issues to the shared device; it’s a Gigabit LAN connection
Maximum number of 255 concurrent connections is not reached
Maximum size of database not exceeded (db has only 5 MB)
Changed the compile option from “Any CPU” to “x86” as suggested in this MS Dev-Net post
Quote: I was getting the same "Cannot open database ''" error, but completely randomly (it seemed). The MDB file was less than 1Mb, so no issue with a 2Gb limit as mentioned a lot with this error.
It worked 100% on 32 bit versions of windows, but I discovered that the issues were on 64 bit installations.
The app was being compiled as "Any CPU".
I changed the compile option from "Any CPU" to "x86" and the problem has disappeared.
Nothing helped so far.
To gather more information, I attached an Nlog logger to the DbContext which writes all database actions and queries to a log file.
Shared Log As Logger = LogManager.GetLogger("DbContext")
Me.Database.Log = Sub(s) Log.Debug(s)
Investigating the logs I figured out that when one of the above errors occured on one server, another one of the servers (3 in total) has closed the db connection at exactly the same time.
Here two examples which correspond to the above errors:
06:33:50 DbContext "Closed connection at 2/12/2020 6:33:50 AM +00:00
14:04:39 DbContext "Closed connection at 2/13/2020 2:04:39 PM +00:00
Assumption
When all connections of a DbContext have been closed, the according record is removed from the .ldb lock file. When a connection to the db is being opened, a record will be added to the lock file. When these two events occur at the exact same time, from two different servers, there is a write conflict to the .ldb lock file, which results in on of the errors from above.
Question
Can anyone confirm or prove this wrong? Has anyone experienced this behaviour? Maybe I am missing something else. I’d appreciate your input and experience on this.
If my assumption is true, a solution could be to use a helper class for accessing db, which catches and handles this error, waiting for a minimal time period and trying again.
But this feels kind of wrong. So I am also open to suggestions for a “proper” solution.
EDIT: The "proper" solution would be using a DBMS Server (as stated in the comments below). I'm aware of this. For now, I have to deal with this design mistake without being responsible for it. Also, I can't change it in the short run.
I write this as an aswer because of space but this is not really an answer.
It's for sure an OleDb provider issue.
I think that is a sharing issue.
You could do some tries:
use a newer OleDb provider instead of Microsoft.Jet.OLEDB.4.0. (if you have try 64 bits you could already have try another provider because Jet.OLEDB.4.0 is 32 bits only)
Implement a retry mechanism on the new DbContext()
Reading your tests this is probaly not your case. I THINK that Dispose does not always work properly on Jet.OLEDB.4.0 connections. I noted it on tests and I solved it using a different testing engine. Before giving up I used this piece of code
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
As you can understand reading this code, they are tries and the latest solution was changing the testing engine.
If your app is not too busy you could try to lock the db using a different mechanism (for example using a lock file). This is not really different from new DbContext() retries.
In late '90s I remember I had an issue related to disk sharing OS (I were using Novel Netware). Actually I have not experience in using mdb files on a network share. You could try to move the mdb on a folder shared with Windows
Actually I use Access databases only for tests. If you really need to use a single file database you could try other solutions: SQL Lite (you need a library, also this written by me, to apply code first https://www.nuget.org/packages/System.Data.SQLite.EF6.Migrations/ ) or SQL Server CE
Use a DBMS Server. This is for sure the best solution. As the writer of JetEntityFrameworkProvider I think that single file databases are great for single user apps (for this apps I suggest SQL Lite), for tests (I think that for tests JetEntityFrameworkProvider is great), for transfering data or, also, for readonly applications. In other cases use a DBMS Server. As you know, with EF, you can change from JetEntityFrameworkProvider to SQL Server or to MySql without effort.
You went wrong at the design stage: The MS Access database engine is unfit for ASP.Net sites, and this is explicitly stated on multiple places, e.g. the official download page under details.
The Access Database Engine 2016 Redistributable is not intended .... To be used by ... a program called from server-side web application such as ASP.NET
If you really have to work with an Access database, you can run a helper class that retries in case of common errors. But I don't recommend it.
The proper solution here is using a different RDBMS which exhibits stateless behavior. I recommend SQL Server Express, which has limitations, but if you exceed those you will be far beyond what Access supports, and wont cause errors like this.

Where to Get Encryption Key for Realm App in Swift

I have a Swift app that uses the Realm Object Server running remotely on a Linux server. Everything is working, including real-time sync.
Occasionally I want to inspect the contents of a local Realm file used by the iOS Simulator so I can do some debugging. When I browse here:
~/.../CoreSimulator/.../Documents/realm-object-server/<unique id>/
...and I try to open this file: realm%3A%2F%2F104%2E236%2E129%2E235%3A9080%2F%7E%2Fmyapp.realm
I get prompted with: Please enter a valid encryption key for this Realm file.
Where do I get this encryption key? I tried using the admin token from the server, but that doesn't appear to be working.
Also, can I turn off encryption everywhere? Or is it mandatory for any app using the Realm Object Server?
It is not possible to open the local version of a synced Realm file using the Browser (or anything else, for that matter). This is due to differing history types internally (but I won't go into that now). In order to inspect the contents of the Realm file, you have to open it using the previously defined syncURL. The browser will then download the file and show you the contents.
A few links on this topic:
https://github.com/realm/RealmTasks/issues/327
https://github.com/realm/realm-core/issues/2276
You may use old version of Realm Browser, please update it and check the result again.
Use Realm Studio instead which worked for me.
Here can download the file
byte[] key = new byte[64];
new SecureRandom().nextBytes(key);
String encryptionKey = byteArrayToHexString(key);
//encryptionKey is what you want byteArrayToHexString see
Log.d("test", "encryptionKey:"+encryptionKey);
byteArrayToHexString() method you can see:How to convert a byte array to a hex string in Java?

SqlCeException database is opened with a read-only connection

We store a template for building SQL Server CE connection strings in our web.config and use string.format to set the data source and temp path values.
In the web.config, the template for the DB connection string is:
"Data Source={0}; Temp Path={1}; Mode=Read Only"
In the web.release.config, we use to build deployment packages, the template for the DB connection string is:
Data Source={0}; Temp Path={1}
Now we only use the SQL Server CE database for read only operations. So, being a smartypants, I thought I would remove the connection string transform in the web.release.config and just always use the read only connection string from the web.config.
This worked fine for the database I was testing. But the same code running with a different SQL Server CE database fails with the following exception:
Exception 'System.Data.SqlServerCe.SqlCeException' with message 'The
database is opened with a read-only connection. Can't perform
post-initialization operations like re-building indexes and upgrading
public tracking. Please re-open with a read-write connection. [
Database name = D:\inetpub\wwwroot\MyApp\App_Data\Storage.sdf ]'
We are using the System.Data.SqlServerCe.4.0 provider
Why in my release build that is deployed to a server does read only access fail for some SQL Server CE databases but not others? It is the same code, just pointing at a different .SDF file. The .SDF files have the same schema, just different data.
Is the driver trying to rebuild indexes because the .SDF file is in some older format? Should we never use a readonly connection in production? Is that why the original code had the transform? why do they all work with a readonly connection on my Windows 7 workstation?
You should always specify a temp path, as moving databases between OS platforms/versions can require index rebuilds.
See my blog post post here: http://erikej.blogspot.dk/2009/08/running-sql-compact-from-cd-rom-read.html for more detailed info.

The underlying provider failed on open entity framework

I am unsing entity framework in my web application. Earlier everything was working fine. But then I deleted database from Sql Server. After that whenever I run the application, I get the following exception :
The underlying provider failed on open entity framework
Isn't it true that if we delete the database from Sql Server and again run the application, database is again created?
Can you show some details about connection string. I basically want to check the authentication you are using.
Demo for setting a typical authentication : http://msdn.microsoft.com/en-us/library/ff649314.aspx
Another possibility can be with connection pooling. Try explicitly closing the connection(if there are any open connections)
db.Database.Connection.Close();
Entity framework will recreate your database on application start assuming the following:
You have permission to create databases in SQL
A connection string is specified correctly (if it was working before this should be fine)
You are using CodeFirst or ModelFirst strategies for databases (ie if you generated an EDMX off an existing database it wont recreate it for you)
I had a similar error and it was due to the connection problem.
Usually you need to open your *.EDPS file under your entity (EDML) and check your connection string and make sure it has got a correct setting especially your Default Oracle home.

Resources