0

This is a followup to a question here

ctacke said there regarding SQL Server CE-related "issues" I was/am having:

"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()."

I know now that the .SDF file in question is version 2.0

So should I use the "SqlCeEngine.Upgrade()" technique somewhere in my code?

Based on the C++ setup utility code, both devices (3090 and 3190, but I'm working testing the 3190 right now) should have SQLCE 2 installed:

cabModule installMC3090[] = {{_T("ceremote.sa1100.CAB"),_T("Microsoft Remote Display Control"),IDR_CEREMDISP,true},
            {_T("netcf.all.wce4.armv4.cab"),_T("Microsoft .NET Compact Framework"),IDR_NETCF,false},
            {_T("OpenNETCF.SDF.WCE4.ARMV4.CAB"),_T("OpenNETCF SDF v1.4"),(DWORD)0,true},
            {_T("sql.wce4.armv4.CAB"),_T("Microsoft SQL Client"),IDR_SQLCLIENT,false},
            {_T("sqlce.dev.wce4.armv4.CAB"),_T("Microsoft SQLCE 2.0 Dev"),IDR_SQLCEDEV,false},
            {_T("sqlce.wce4.armv4.CAB"),_T("Microsoft SQLCE 2.0"),IDR_SQLCE,false},
            {_T("symbol.all.arm.cab"),_T("Symbol Managed Class Libraries"),IDR_SYMBOL,false},
            {_T("System_SR_enu.cab"),_T("Microsoft .NET CF 1.0 ENU-String Resource"),IDR_NETRESOURCES,false},
            {_T("HHS_WCE4.ARMV4.CAB"),_T("SSCS HHS"),IDR_HHS,false},
            {_T("END"),_T("END"),(DWORD)0,false}
};

//MC3190 includes .NET 3.5 in the default configuration
cabModule installMC3190[] = {{_T("ceremote.sa1100.CAB"),_T("Microsoft Remote Display Control"),IDR_CEREMDISP,true},
            {_T("OpenNETCF.SDF.WCE4.ARMV4.CAB"),_T("OpenNETCF SDF v1.4"),(DWORD)0,true},
            {_T("sql.wce4.armv4.CAB"),_T("Microsoft SQL Client"),IDR_SQLCLIENT,false},
            {_T("sqlce.dev.wce4.armv4.CAB"),_T("Microsoft SQLCE 2.0 Dev"),IDR_SQLCEDEV,false},
            {_T("sqlce.wce4.armv4.CAB"),_T("Microsoft SQLCE 2.0"),IDR_SQLCE,false},
            {_T("symbol.all.arm.cab"),_T("Symbol Managed Class Libraries"),IDR_SYMBOL,false},
            {_T("NETCFv35.Messages.EN.cab"),_T("Microsoft .NET CF 3.5 EN-String Resource"),IDR_NETRESOURCES,true},
            {_T("HHS_WCE4.ARMV4.CAB"),_T("SSCS HHS"),IDR_HHS,false},
            {_T("END"),_T("END"),(DWORD)0,false}
};

....though I can't find any "SQLCE" files anywhere on the device...

UPDATE

I added a call to Upgrade() after instantiating the SqlCeEngine:

engine = new SqlCeEngine(conStr);
engine.Upgrade(conStr); // <= this is new

...and that may have been a good thing, because now the err msg is a different one, to wit:

location: DBConnection.DBConnection

Exception: The password specified for the source database is incorrect [ Data Source = \My Documents\HHSDB.SDF ]

Inner Exception: [ blank ]

TypeFullName: System.Data.SqlServerCe.SqlCeException

StackTrace: ProcessResults, Repair...

Compare that with what it had been in Update 4 here (now it's a password problem; previously it seemed to be a Sql Ce version mismatch problem).

Okay, so the legacy code (which had worked previously) does not seem to add a password. How is a password normally "tacked on" (not that I even know at this point what the password should be)? Is there a way to get it NOT to expect a password?

Here is the DBConnection instantiation code, which may shed some light on this:

public class DBConnection
{
    public string filename = HHSUtils.GetDataPath() + "HHSDB.SDF";
    SqlCeConnection objCon = null;
    SqlCeEngine engine;

    private DBConnection()
    {
    try
    {
    // Connection String
    //string conStr = "Data Source = " + filename; <== this is the legacy, but failing for some reason (see https://stackoverflow.com/questions/23438579/in-what-format-does-sqlceconnection-expect-its-connection-string-arg/23438672)
    //string conStr = string.Concat("Data Source = ", Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "HHSDB.SDF"));
    filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "HHSDB.SDF");
    string conStr = string.Concat("Data Source = ", filename);
    engine = new SqlCeEngine(conStr);
    engine.Upgrade(conStr); 

The formerly used GetDataPath(), which is called by the assignment to filename but is now moot because filename is overwritten, is simply:

public static string GetDataPath()
{
    return @"\My Documents\";
}

UPDATE 2

Is this enough to solve my problem, simply to append "Persist Security Info=False;" to the connection string, a la:

Data Source=MyData.sdf;Persist Security Info=False;

? IOW, is appending that a way of saying, "forget about passwords, I'm not relying on them"?

I also notice that the example above (from here) has no spaces between "Source" and "=" and between "=" and the path to the SDF file. Is this unimportant (as I suspect - IOW, either way should work)?

Perhaps more importantly, though, my connection string begins with a whack ("Data Source = \My Documents") whereas this one does not. Significant?

According to that same site, if I do need a password, I reckon it would be like so:

Data Source=MyData.sdf;Encrypt Database=True;Password=myPassword;
File Mode=shared read;Persist Security Info=False;

...or...???

UPDATE 3

Altho ctacke says the cab installations are not really relevant, in the interest of completeness/for posterity I am adding some notes I made on how the device's setups differ:

Those cab files marked with an asterisk differ from the other device's installation

3090 gets 8 cabs installed via the setup utility:

HHS_WCE4.ARMV4.CAB
*netcf.all.wce4.armv4.cab
OpenNETCF.SDF.WCE4.ARMV4.CAB
sql.wce4.armv4.CAB
sqlce.dev.wce4.armv4.CAB
sqlce.wce4.armv4.CAB
symbol.all.arm.cab
*System_SR_enu.cab

3190 gets 8 cabs installed via the setup utility (a comment in the setup utility says, "MC3190 includes .NET 3.5 in the default configuration"):

*ceremote.sa1100.CAB
HHS_WCE4.ARMV4.CAB
*NETCFv35.Messages.EN.cab
OpenNETCF.SDF.WCE4.ARMV4.CAB
sql.wce4.armv4.CAB
sqlce.dev.wce4.armv4.CAB
sqlce.wce4.armv4.CAB
symbol.all.arm.cab

So:

3090 has uniquely:

netcf.all.wce4.armv4.cab
System_SR_enu.cab

3190 has uniquely:

ceremote.sa1100.CAB
NETCFv35.Messages.EN.cab

Both get upgrades to:

HHS_WCE4.ARMV4.CAB
symbol.all.arm.cab

(why these "upgrade cabs" are not simply added in their respective install lists, I don't know - is there an "Upgrade" option?)

UPDATE 4

Inspired (provoked, prodded) by ctacke's latest comment, I looked closely at the SQL CE references I have in my app, and it looks like a putrid potion of mish-mashed mixing and matching:

System.Data is runtime 2.0.0.0 and Version the same (2.0.0.0)
System.Data is from C:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v2.0\WindowsCE\System.Data.dll

System.Data.SqlClient is runtime version v2.0.50727 and Version 3.0.3600.0 
System.Data.SqlClient is from C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\Devices\Client\System.Data.SqlClient.dll

System.Data.SqlServerCe is  runtime version v2.0.50727 and Version 3.5.1.0
System.Data.SqlServerCe is from C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\Devices\System.Data.SqlServerCe.dll

Maybe this witches brew has at least something to do with my problems.

UPDATE 5

So, I thought, surely this is some cross between Frankenstein and Dracula that I've got here. These related files must all exist in the same location. So I looked at all of them and found this:

C:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v2.0\WindowsCE
System.Data.dll == 2/14/2007 
System.Data.SqlClient.dll == [not there]
System.Data.SqlServerCe.dll == [not there]

C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\Devices\Client
System.Data.dll == [not there]
System.Data.SqlClient.dll == 7/3/2007
System.Data.SqlServerCe.dll == [not there]

C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\Devices
System.Data.dll == [not there]
System.Data.SqlClient.dll == [not there]
System.Data.SqlServerCe.dll == 2/12/2010

Say it ain't so! Is this really how things stand - I have to get this file from here, that one from there, etc.?

UPDATE 6

In reponse to this comment from ctacke:

"the version of SQL CE you are referencing must match that on the device down to the revision. I can't tell you what it should be, just that they must be the same, and they should match down to the minor version whatever created the database file"

I see no SqlServerCe.dll on the device at all; there is a folder named "Computer\Clay's Device\\Program Files\Microsoft SQL Server Compact Edition\v3.5" that has the following DLLs:

sqlceca35.dll
sqlcecompact35.dll
sqlceer35EN.dll
sqlceme35.dll
sqlceoledb35.dll
sqlceqp35.dll
sqlcese35.dll

(all created 2/12/2010)

There is also a folder on the devie, "Computer\Clay's Device\\Windows\SQLCE 2.0" that contains files dated 8/16/2002 and 8/28/2002:

ssce20.dll
ssceca.dll
ssceerror20en.dll
ssceerror20jp.dll

I assume the last two are for displaying error messages, and I assume the last one is for japanese, and I don't think we have any Japanese customers (and certainly there is no localized version of the app in Japanese), so that's kind of baffling.

So there is no SqlServerCe.dll on the handheld device at all, so no conflict between versions is possible - unless SqlServerCe.dll is there somewhere but invisible?

UPDATE 7

As a followup to Update 5 and for completeness' sake (the first two DLL files may be "uninteresting"):

I searched my entire hard drive for the three files:

System.Data.dll was found, besides where noted above, in:

C:\Program Files (x86)\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\WindowsCE
Creation Date = 11/24/2002; Size = 403KB

C:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v2.0\Debugger\BCL
Creation Date = 2/14/2007; Size = 696KB

C:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v3.5\Debugger\BCL
Creation Date = 10/10/2007; Size = 710KB

C:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v3.5\WindowsCE
Creation Date = 10/10/2007; Size = 124KB

System.Data.SqlClient.dll was found, besides where noted above, in several places, but they are all the same in size except for:

C:\Program Files (x86)\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\WindowsCE
where it is 148KB (creation date of 9/24/2002)

System.Data.SqlServerCe.dll was found, besides where noted above (C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\Devices), in:

C:\Program Files (x86)\Microsoft Visual Studio .NET 2003\CompactFrameworkSDv1.0.50000\WindowsCE
9/24/2002; 124KB

C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.1
12/22/2006; 236KB

Also in:

C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\Desktop
C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v3.5\Private
C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v4.0\Desktop
C:\Program Files (x86)\Microsoft SQL Server Compact Edition\v4.0\Private

-and in (same as above but in the Program Files folder without the "(x86)"):

C:\Program Files\Microsoft SQL Server Compact Edition\v3.5\Desktop
C:\Program Files\Microsoft SQL Server Compact Edition\v3.5\Private
C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Desktop
C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Private
Community
  • 1
  • 1
B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862
  • 1
    The password is set at database creation time. You need to look at whatever code created that file. It's part of the connection string. – ctacke May 05 '14 at 23:55
  • 1
    Encrypt is separate from having a password. You can have a password with no encryption (but you must have a password to have encryption). File Mode defaults to shared read. Persist Security Info I believe is a NOP in Compact. Setting it to false does not remove the password, as that would eliminate the whole point of password protecting the file. If the database was created with a password, you need that password to open it. If you have an app that has ever opened it properly, or that created it, use Reflector and go get the password. – ctacke May 06 '14 at 03:03
  • Previous builds open it fine, and I have not added, removed, or changed the password. I didn't even know there was a password associated with it until now. – B. Clay Shannon-B. Crow Raven May 06 '14 at 15:38
  • 1
    FWIW, the "installed CABs" is not overly relevant. The application will use the SQL CE version that the app was referencing, so if you reference 3.5, installing 2.0 won't make the app use 2.0. It will still try to use 3.5. You need to be absolutely certain that the version you have as a reference in the app is the same as the one you deploy, down to the minor version number. – ctacke May 06 '14 at 15:51
  • Where does my app / how can my app reference a specific SQL CE version? The only version-specific thing I see in the code is the call to Upgrade() which you recommended, and which seemed to work, but I don't know what version it's upgrading from or to. – B. Clay Shannon-B. Crow Raven May 06 '14 at 15:57
  • AFAICT, I simply build a connection string and then attempt to open the .SDF file; I see no expectation or coercion of SQL CE version anywhere in my code. Should there be? Does the lack of such default to a certain version? – B. Clay Shannon-B. Crow Raven May 06 '14 at 16:13
  • It's in the project references. You've referred to "System.Data.SqlCe" and that reference has a version. – ctacke May 06 '14 at 17:22
  • I have System.Data.SqlClient, which is runtime Version v2.0.50727 and Version 3.0.3600.0 and System.Data.SqlServerCe, which is Version v2.0.50727 and Version 3.5.1.0 – B. Clay Shannon-B. Crow Raven May 06 '14 at 17:40
  • You have two referenced versions of SqlServerCe in there? That's a problem. You should have one and only one 9and based on what I'm seeing, it should be the 2.0 version). – ctacke May 06 '14 at 18:11
  • One is System.Data.SQLClient.dll and the other is System.Data.SqlServerCE.dll - that's a problem? They are both runtime version v2.0.50727 – B. Clay Shannon-B. Crow Raven May 06 '14 at 18:39
  • SqlClient has nothing to do with it. You're probably not even using it. It's for connecting to an external SQL Server database. – ctacke May 06 '14 at 18:41
  • Okay, but I still only reference SqlServerCe once. Would removing SQLClient.dll possibly solve a problem, or is it just extra baggage that may or may not get optimized it if unused? – B. Clay Shannon-B. Crow Raven May 06 '14 at 18:47
  • Again, the version of SQL CE you are referencing must match that on the device down to the revision. I can't tell you what it should be, just that they must be the same, and they should match down to the minor version whatever created the database file. – ctacke May 06 '14 at 18:50
  • Okay, but I don't know if I have any way of knowing what created the database file. I should, yes, but I don't see any creation code of it in either the install util or the app itself. – B. Clay Shannon-B. Crow Raven May 06 '14 at 19:05
  • New related question here: http://stackoverflow.com/questions/23505211/which-sqlserverce-dll-version-do-i-need-to-reference-in-my-project-to-match-what – B. Clay Shannon-B. Crow Raven May 06 '14 at 21:56

0 Answers0