1

I have a call to SqlCeConnection.Open() that's failing. The exception message I'm getting is pretty generic: "System.Data.SqlserverCe.SqlCeException" (more generic than pretty)

The pertinent code is:

private DBConnection()
{
    try
    {
        string conStr = "Data Source = " + filename;
        string cmpStr = conStr + ".tmp";
        if (File.Exists(filename+".tmp"))
            File.Delete(filename+".tmp");

        engine = new SqlCeEngine(conStr);

        if (File.Exists(filename))
        {
        }
        else
        {
            engine.CreateDatabase();

            }
        engine.Dispose();

        objCon = new SqlCeConnection(conStr);                                                                           
            //MessageBox.Show(string.Format("conStr == {0}", conStr)); 
        objCon.Open(); // <= This is where all Dallas breaks loose; conStr is "DataSource = \My Documents\NRPSDB.SDF" (which file *does* exist on the device)
    }
    catch(Exception ex)
    {
        NRPS.ExceptionHandler(ex, "DBConnection.DBConnection");
    }
}

Is the problem the connection string arg passed to the SqlCeConnection constructor? Is the "DataSource =" preamble unnecessary/problematic? Do the backwhacks need to be doubled or assigned to a verbatim string? Or...???

For more info, see this scintillating exchange:

UPDATE

Grant Winney's answer looked promising, but trying it today, I find that it doesn't compile in my (Windows CE / CF) situation. The possibilities for me following "SpecialFolder" are:

ApplicationsData
Favorites
Personal
Programs
StartMenu
Startup

None of these correspond to "MyDocuments" do they?

UPDATE 2

Expanded response to ctacke's comment below:

Here is the place where the SqlCe exception gets embedded within a MessageBox.Show() "debug" string:

public static string GetFormTitle(string formName, string serialNo, string siteNo)
{
    MessageBox.Show(string.Format("GetFormTitle() reached. formName == {0}; serialNo == {1}; siteNo == {2}", formName, serialNo, siteNo)); // TODO: Remove after testing
    string titleBar = formName == "" ? "NRPS HHS" : formName;

What I end up seeing is:

"GetFormTitle() reached. formName == NRPS: System.Data.SqlServerCe.SqlCeException; serialNo == ; siteNo == ;"

A related post/thread is here

UPDATE 3

The bizarro custom exception handler does attempt to show exception detail like so:

public static void ExceptionHandler(Exception ex, string location)
{
    try
    {
        MessageBox.Show("Exception: " + ex.Message + "\n\nLocation: " + location, GetFormTitle("NRPS: " + ex.GetType().FullName,"",""));
    }
    catch(Exception exc)
    {
        MessageBox.Show("Exception Handler generated an exception!\n" + exc.Message + "\n\nCalling Location: " + location, GetFormTitle("NRPS: " + exc.GetType().FullName,"",""));
    }
}

UPDATE 4

Now we're getting somewhere maybe. I commented out the existing line in the custom exception handler that called GetFormTitle() and replaced it with this:

MessageBox.Show(string.Format("location: {0}; Exception: {1}; Inner Exception: {2}; TypeFullName: {3}; StackTrace: {4}" + location, ex.Message, ex.InnerException, ex.GetType().FullName, ex.StackTrace));

This is what I see now:

"location: DBConnection.DBConnection:

Exception: Incompatible Database Version. If this was a compatible file, run repair. For other cases refer to documentation. [DB version = 0,Requested version = 0,File name = My Documents\HHSDB.SDF ];

Inner Exception: TypeFullName: System.Data.SqlServerCe.SqlCeException;

StackTrace: at System.Data.SqlServerCe.SqlCeConnection.ProcessResults(Int 32 hr) at System.Data.SqlServerCe.SqlCeConnection.Open(boolean silent) at System.Data.SqlServerCe.SqlCeConn... [can't see any more...]*"

This is what strikes me: DB version = 0,Requested version = 0

But...what the Hec Ramsey?!?

UPDATE 5

This has morped into a new question, which I posted here

UPDATE 6

And that one to another, which is here

Community
  • 1
  • 1
B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 1
    What's the actual exception you're getting? If the `CreateDatabase()` call with the setting is succeeding, that indicates it's a valid connection string and you have some other issue. – ctacke May 05 '14 at 16:23
  • It's very bizarre: an exception embedded within MessageBox.Show(). Specifically, it is: "[my verbiage] System.Data.SqlServerCe.SqlCeException; [more of my verbiage]" – B. Clay Shannon-B. Crow Raven May 05 '14 at 16:27
  • For a fuller response, see Update 2 – B. Clay Shannon-B. Crow Raven May 05 '14 at 16:30
  • 1
    SqlCeException usually contains an InnerException as well. The error text you've got above suggests an error in your messagebox call, which makes me think you're getting the exception not with the exact code you have posted above. – ctacke May 05 '14 at 16:31
  • 1
    Put code in the exception handler. Have it output the exception. Don't try having it done elsewhere, as that's just adding chaff to the wheat. While you're at it, make sure the DB file isn't marked read-only and that it doesn't have a password set. – ctacke May 05 '14 at 16:33
  • The MessageBox() in Update 2 was copied verbatim. – B. Clay Shannon-B. Crow Raven May 05 '14 at 16:33
  • "While you're at it, make sure the DB file isn't marked read-only and that it doesn't have a password set." It's not marked read-only (easy to check), but how do I see whether it "has a password set"? – B. Clay Shannon-B. Crow Raven May 05 '14 at 16:40
  • 1
    You would have created it with a password (e.g. when copying from a PC). Is this an empty DB? Where was it created? If it was created on the desktop or another device, if the SQL CE Version isn't the same, you could hit problems. – ctacke May 05 '14 at 16:41
  • The database is created via an install process - another .exe runs on the handheld, setting up the environment, etc. I know little to nothing about it (and it's written in C++). – B. Clay Shannon-B. Crow Raven May 05 '14 at 16:48
  • It's EXTREMELY bizarre to me that that SQLCe exception would appear in the midst of that harmless-looking MessageBox.Show() - all it's doing is showing the values of some strings! – B. Clay Shannon-B. Crow Raven May 05 '14 at 16:53
  • The custom exception handler (see update 3) is calling GetFormTitle(). Don't ask why it works this way, because I don't know. – B. Clay Shannon-B. Crow Raven May 05 '14 at 16:58
  • Yeah, sorry about that; one is the real string, and the other is the one I use to "protect the innocent" (and the guilty). At any rate, it means little - just an acronym in both cases. I made them all "New Riders of the Purple Sage" now. – B. Clay Shannon-B. Crow Raven May 05 '14 at 17:22

2 Answers2

2

The problem, as indicated by the error text, is that the SDF file was created by a version of SQL Compact that doesn't match the version of SQL Compact that the application is referencing. I wouldn't focus on the reported version numbers, just the fact that it knows there's a mismatch.

If you don't know the version of the SDF, you can always look it up by reading a few bytes from the SDF file.

SQL Compact database files aren't 100% transportable. You definitely cannot take an SDF from a newer version and load it with an older set of runtimes.

If the database was created with 3.1, you can upgrade it to 3.5 by calling SqlCeEngine.Upgrade().

You cannot programmatically upgrade from 1.0 or 2.0 to any newer version. You must use the older SQL Compact libraries to interact with the database or you must recreate the database targeting the newer runtimes.

If the database was created on a PC, the first use will force a full re-index because the indexes are formatted differently on a device. If you have a lot of data in the database, it's often best to make sure what you deploy to the device was actually last opened on a device to prevent users from having to wait for that re-index.

ctacke
  • 66,480
  • 18
  • 94
  • 155
  • "The problem, as indicated by the error text, is that the SDF file was created by a version of SQL Compact that doesn't match the version of SQL Compact that the application is referencing." This seems very odd to me, as the database file is created programmatically by a separate setup app (I run that on the device, and the SDF files are then created in the "My Documents" folder). Actually, I just looked at them, and see that two SDF files are dated 4/30/2014 (when I cold-booted the device, then ran that setup util), and one is dated 1/1/2009 (???). At any rate, the one being referenced is new – B. Clay Shannon-B. Crow Raven May 05 '14 at 19:07
  • Unfortunately, that link's download link is stale or bogus. Would it be possible to copy the file to my PC and then peek into it using .NET Reflector or some such to spy on the "location at offset 16 and read the 32 bit int there." – B. Clay Shannon-B. Crow Raven May 05 '14 at 19:15
  • This has morped into a new question, which I posted here: http://stackoverflow.com/questions/23481551/how-to-decipher-interpret-the-contents-of-a-file-as-shown-in-a-hex-editor – B. Clay Shannon-B. Crow Raven May 05 '14 at 20:46
1

Since filename contains the relative path "\My Documents\NRPSDB.SDF", your program may be looking for that path starting at the directory your application is running from, which is most likely the wrong place. Something like:

... \bin\debug\My Documents\NRPSDB.SDF

Try placing this in your method and see if it's able to find the file:

string conStr = string.Concat("Data Source = ",
   Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                "NRPSDB.SDF"));

If it is able to find it, then you'll have to use this wherever you're calling the method from, so that filename contains the correct absolute path.


Regarding your update that you're using Win CE, the equivalent to SpecialFolder.MyDocuments is SpecialFolder.Personal.

From MSDN:

Personal. The directory that serves as a common repository for documents. This member is equivalent to MyDocuments.

Grant Winney
  • 65,241
  • 13
  • 115
  • 165
  • No, it's definitely in "\My Documents\NRPSDB.SDF" on the handheld device where it's running. I'll try your suggestion (Monday) though - thanks! – B. Clay Shannon-B. Crow Raven May 04 '14 at 00:52
  • 1
    That's not a relative path. It starts with a slash, making it absolute. And it wouldn't look in `...\bin\debug...` as it's running on a device. – ctacke May 05 '14 at 16:21
  • We've not got enough info for me to know the error, though I have a couple suspicions – ctacke May 05 '14 at 16:28
  • The "Environment.SpecialFolder.Personal" tip from Grant does work, as to referencing the "My Documents" folder; that's why I marked it an answer to the question. But it's still breaking, as evidenced by Update 2. – B. Clay Shannon-B. Crow Raven May 05 '14 at 16:47