Comment déployer Microsoft SQL Server Compact 4. ?
SQL Server Compact Edition (actuellement à la version 4.0) est:
une base de données intégrée gratuite que les développeurs de logiciels peuvent utiliser pour créer des applications de bureau Windows. Il a une petite empreinte et prend en charge le déploiement privé de ses fichiers binaires dans le dossier d'application.
Mais comment le déployez-vous réellement?
Le problème est que vous ne pouvez pas utiliser le fournisseur OLEdb ADO sauf s'il est enregistré. L'enregistrement d'un fournisseur OLEdb doit être effectué en tant qu'administrateur. Cela signifie que l'édition SQL Server Compact échouera avec les utilisateurs qui sont pas un administrateur.
SQL Server Compact 4.0 est fourni avec un redist_enu.txt
fichier:
Les fichiers .exe répertoriés installent chacun leurs composants inclus à un emplacement spécifique sur l'ordinateur de destination. Cela permet de garantir la maintenance et le support technique. Les fichiers .dll inclus dans ces fichiers .exe sont également disponibles séparément dans ce redist.txt. Toutefois, les distributions de ces fichiers .dll distincts peuvent entraîner des problèmes de facilité de maintenance. Pour plus de détails, veuillez consulter http://go.Microsoft.com/fwlink/?LinkId=94589
Détection de déploiement privé via BreadCrumb: le déploiement privé de la pile native uniquement et le chargement explicite de SQL Server Compact Assembly via Assembly.LoadFrom (), le fichier .local ou l'utilisation de stratégies de redirection DLL/COM ne sont pas pris en charge et peuvent entraîner des problèmes de facilité de maintenance . Pour plus d'informations, voir http://support.Microsoft.com/kb/835322 et http://msdn2.Microsoft.com/en-us/library/aa375142.aspx =
Microsoft SQL Server Compact 4.0
SSCERuntime_x86-ENU.exe
SSCERuntime_x86-DEU.exe
SSCERuntime_x86-FRA.exe
SSCERuntime_x86-JPN.exe
SSCERuntime_x86-RUS.exe
SSCERuntime_x86-ESN.exe
SSCERuntime_x86-ITA.exe
SSCERuntime_x86-KOR.exe
SSCERuntime_x86-CHT.exe
SSCERuntime_x86-CHS.exe
SSCERuntime_x64-ENU.exe
SSCERuntime_x64-DEU.exe
SSCERuntime_x64-FRA.exe
SSCERuntime_x64-JPN.exe
SSCERuntime_x64-RUS.exe
SSCERuntime_x64-ESN.exe
SSCERuntime_x64-ITA.exe
SSCERuntime_x64-KOR.exe
SSCERuntime_x64-CHT.exe
SSCERuntime_x64-CHS.exe
sqlcese40.dll
sqlceqp40.dll
sqlceoledb40.dll
sqlceca40.dll
sqlceme40.dll
sqlcecompact40.dll
sqlceer40en.dll
sqlceer40cn.dll/sqlceer40zh-CHS.dll
sqlceer40de.dll
sqlceer40es.dll
sqlceer40fr.dll
sqlceer40it.dll
sqlceer40ja.dll
sqlceer40ko.dll
sqlceer40tw.dll/sqlceer40zh-CHT.dll
sqlceer40ru.dll
System.Data.SqlServerCe.dll
System.Data.SqlServerCe.Entity.dll
mais il ne donne aucune information sur la redistribution de SQL Server Compact 4.0.
Épeler au hasard les sans-papiers Program Files
dossier j'ai trouvé 7 DLL:
C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\
sqlceoledb40.dll
sqlceqp40.dll
sqlcese40.dll
sqlceca40.dll
sqlcecompact40.dll
sqlceer40EN.dll
sqlceme40.dll
Remarque: Il existe également des dossiers enfants avec plus de DLL
j'ai essayé de copier ces 7 DLL dans un dossier et j'ai essayé d'ouvrir une connexion ADO en utilisant la chaîne de connexion :
Provider=Microsoft.SQLSERVER.CE.OLEDB.4.0;Data Source="store.sdf"
mais il échoue avec 0x80004005 Unspecified error
j'ai essayé de frobber le widget, mais il a grobé le frobber.
j'ai créé la solution.
SQL Server Compact Edition est composé de 7 DLL:
sqlceme40.dll
La bibliothèque d'API plate, non documentée et native (L'assembly .net System.Data.SqlServerCe.dll
Est un wrapper autour de cette DLL)sqlceca40.dll
Une DLL COM qui implémente Engine
, Replication
, Error
et quelques autres objets COMsqlceoledb40.dll
Une DLL COM qui implémente un fournisseur OLEdb pour SSCE (autorisant l'utilisation d'ADO)sqlcese40.dll
inconnusqlceqp40.dll
inconnusqlcecompact40.dll
inconnusqlceer40en.dll
inconnuLe problème avec la tentative de simplement envoyer ces DLL est que deux d'entre eux sont des objets [~ # ~] com [~ # ~] . La DLL de l'objet COM doit être enregistrée, par exemple:
>regsvr32 sqlceca40.dll
>regsvr32 sqlceoledb40.dll
Le problème est que l'enregistrement d'un objet COM nécessite des privilèges administratif ( en utilisant une solution globale pour résoudre un problème local ). Cela signifie que vos utilisateurs
Heureusement, à partir de 2001 avec Windows XP, Microsoft a résolu ce problème COMmon: Registration-Free COM .
Tout d'abord, vous déclarerez que votre application a un "dépendance" sur SQL Server Compact Edition 4.0. Pour ce faire, créez un manifeste d'assembly:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Assembly xmlns="urn:schemas-Microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="client"
type="win32"
/>
<description>Hyperion Pro</description>
<!-- We have a dependancy on SQL Server CE 4.0 -->
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.SQLSERVER.CE.4.0"
version="4.0.0.0" processorArchitecture="x86"
/>
</dependentAssembly>
</dependency>
<!-- We are high-dpi aware on Windows Vista -->
<asmv3:application xmlns:asmv3="urn:schemas-Microsoft-com:asm.v3">
<asmv3:windowsSettings
xmlns="http://schemas.Microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
<!-- We were designed and tested on Windows 7 -->
<compatibility xmlns="urn:schemas-Microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--The ID below indicates application support for Windows Vista -->
<!--supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/-->
</application>
</compatibility>
<!-- Disable file and registry virtualization -->
<trustInfo xmlns="urn:schemas-Microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</Assembly>
Vous pouvez placer ce fichier à côté de votre exécutable (comme Hyperion.exe.manifest
), Ou vous pouvez l'intégrer dans votre application en tant que ressource RT_MANIFEST
.
Notez que nous avons une dépendance par rapport à l'assembly appelé Microsoft.SQLSERVER.CE.4.0
. Nous créons d'abord cet assemblage en créant un répertoire appelé:
Microsoft.SQLSERVER.CE.4.0
Lorsque vous déployez votre application, vous placerez les 7 dll qui composent ce "Assembly" dans ce sous-dossier Microsoft.SQLSERVER.CE.4.0
, Avec un fichier spécial .manifest
:
C:\
|---Users
|---Ian
|---AppData
|---Local
|---Hyperion Pro
| Hyperion.exe
| Hyperion.exe.manifest
|----Microsoft.SQLSERVER.CE.4.0
sqlceme40.dll
sqlceca40.dll
sqlceoledb40.dll
sqlcese40.dll
sqlceqp40.dll
sqlcecompact40.dll
sqlceer40en.dll
Microsoft.SQLSERVER.CE.4.0.manifest
En d'autres termes, le dossier d'application contient votre application et le dossier Microsoft.SQLSERVER.CE.4.0 :
Directory of C:\Users\Ian\AppData\Local\Hyperion Pro
05/29/2012 09:23 AM 1,899,008 Hyperion.exe
05/28/2012 01:46 PM 1,587 Hyperion.exe.manifest
05/29/2012 09:27 AM <DIR> Microsoft.SQLSERVER.CE.4.0
2 File(s) 1,900,675 bytes
1 Dir(s) 20,851,503,104 bytes free
La prochaine étape de votre tâche consiste à définir le fichier Microsoft.SQLSERVER.CE.4.0.manifest
. COM sans inscription permet à un fichier manifeste de déclarer tous les objets COM et leurs identifiants. Cela a pris beaucoup d'ingénierie inverse. Mais le manifeste d'assembly pour SQL Server Compact Edition 4.0 est:
Microsoft.SQLSERVER.CE.4.0.manifest :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Assembly xmlns="urn:schemas-Microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="Microsoft.SQLSERVER.CE.4.0"
processorArchitecture="x86"
version="4.0.0.0" />
<!-- OLEDB Provider -->
<file name = "sqlceoledb40.dll">
<comClass
description = "Microsoft SQL Server Compact OLE DB Provider for Windows"
clsid="{2006C53A-C915-41EA-BAA9-9EAB3A1FBF97}"
threadingModel = "Both"
progid = "Microsoft.SQLSERVER.CE.OLEDB.4.0" />
</file>
<!-- Native flat engine library -->
<file name="sqlceme40.dll" />
<!-- Engine and Replication COM object -->
<file name="sqlceca40.dll">
<comClass description="Active SSCE Engine Object"
clsid="{68D45319-3702-4837-9F8E-DA6845D82482}"
threadingModel="Both"
progid="SSCE.Engine.4.0" />
<comClass description="SSCE Error Object"
clsid="{36228F21-B5C7-4054-8DC2-47D3E236E8B5}"
threadingModel="Both"
progid="SSCE.Error.4.0" />
<comClass description="SSCE Param Object"
clsid="{0B3A7B75-A9B0-4580-9AA5-1A7DA47AD1CB}"
threadingModel="Both"
progid="SSCE.Param.4.0" />
<comClass description="Active SSCE Replication Object"
clsid="{11D5B2D4-26A4-44F5-A48B-0FAC3A919ED8}"
threadingModel="Both"
progid="SSCE.Replication.4.0" />
<comClass description="Active SSCE remote data access Object"
clsid="{58BC9AD6-BF11-40B3-9AB1-E3F2ED784C08}"
threadingModel="Both"
progid="SSCE.RemoteDataAccess.4.0" />
<typelib tlbid="{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}"
version="4.0"
helpdir=""/>
</file>
<comInterfaceExternalProxyStub
name="ISSCEEngine"
iid="{10EC3E45-0870-4D7B-9A2D-F4F81B6B7FA2}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCEError"
iid="{31155A3B-871D-407F-9F73-DEBFAC7EFBE3}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCERDA"
iid="{4F04F79D-1FF1-4DCD-802B-3D51B9356C14}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCEParams"
iid="{A78AFF90-049C-41EC-B1D8-665968AAC4A6}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCEParam"
iid="{A9876C60-2667-44E5-89DB-E9A46ED392C0}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCEErrors"
iid="{C40143CA-E9F9-4FF4-B8B4-CC02C064FC1B}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<comInterfaceExternalProxyStub
name="ISSCEMerge"
iid="{C6EB397F-D585-428D-A4F4-454A1842CB47}"
proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
baseInterface="{00000000-0000-0000-C000-000000000046}"
tlbid = "{CE4AACFA-3CFD-4028-B2D9-F272314F07C8}" />
<file name="sqlceqp40.dll" />
<file name="sqlcese40.dll" />
<file name="sqlcecompact40.dll" />
<file name="sqlceer40EN.dll" />
</Assembly>
Le dernier problème est que, de la même manière que nous avons une dépendance sur un assembly appelé Microsoft.SQLSERVER.CE.4.0
, SQL Server Compact Edition 4.0 a à son tour une dépendance sur un assembly appelé Microsoft.VC90.CRT
. Heureusement, votre installation de SQLCE est livrée avec une copie de cet assembly:
|----Microsoft.VC90.CRT
| Microsoft.VC90.CRT.manifest
| msvcr90.dll
Cela signifie que la structure finale du répertoire est:
C:\
|---Users
|---Ian
|---AppData
|---Local
|---Hyperion Pro
| Hyperion.exe
| Hyperion.exe.manifest
|----Microsoft.SQLSERVER.CE.4.0
| Microsoft.SQLSERVER.CE.4.0.manifest
| sqlceme40.dll
| sqlceca40.dll
| sqlceoledb40.dll
| sqlcese40.dll
| sqlceqp40.dll
| sqlcecompact40.dll
| sqlceer40en.dll
|---Microsoft.VC90.CRT
| Microsoft.VC90.CRT.manifest
| msvcr90.dll
Pour Sql Server Ce 4.0 SP1:
Au lieu de s'attaquer à toutes les choses sérieuses du déploiement, j'ai simplement choisi d'inclure les fichiers d'installation eux-mêmes dans mon exe en tant que EmbeddedResource et j'ai fait cette petite aide:
public static class RedistHelper
{
private static readonly ILog Log = LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string SqlCeRedistName64 = "SSCERuntime_x64-ENU.exe";
private static readonly string SqlCeRedistName32 = "SSCERuntime_x86-ENU.exe";
private static readonly Dictionary<string, Assembly> Assemblies =
new Dictionary<string, Assembly>(StringComparer.OrdinalIgnoreCase);
private static string SqlCeRedistName
{
get
{
return Environment.Is64BitOperatingSystem
? SqlCeRedistName64
: SqlCeRedistName32;
}
}
public static bool IsSqlCeInstalled()
{
RegistryKey localKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
RegistryView.Registry64);
RegistryKey ret = localKey.OpenSubKey(
@"SOFTWARE\Microsoft\Microsoft SQL Server Compact Edition\v4.0\ENU");
return ret != null;
}
private static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
ms.Write(buffer, 0, read);
return ms.ToArray();
}
}
public static Assembly OnCurrentDomainOnAssemblyResolve(object sender,
ResolveEventArgs args)
{
Assembly dll;
var name = new AssemblyName(args.Name).Name + ".dll";
if (!Assemblies.TryGetValue(name, out dll))
{
Assembly res = typeof(RedistHelper).Assembly;
using (Stream input =
res.GetManifestResourceStream(typeof(RedistHelper), name))
{
if (input == null)
{
Log.WarnFormat("Assembly {0} does not contain {1}", res, name);
return null;
}
dll = Assembly.Load(ReadFully(input));
if (dll == null)
{
Log.WarnFormat("Assembly {0} failed to load.", name);
return null;
}
Log.InfoFormat("Loaded Assembly {0}.", name);
Assemblies[name] = dll;
return dll;
}
}
return dll;
}
public static void InstallSqlCe()
{
using (Stream stream =
typeof(RedistHelper).Assembly.GetManifestResourceStream(
typeof(RedistHelper), SqlCeRedistName))
{
Debug.Assert(stream != null);
byte[] bytes = new byte[(int)stream.Length];
stream.Read(bytes, 0, bytes.Length);
string path = Path.Combine(Path.GetTempPath(), SqlCeRedistName);
if (File.Exists(path))
File.Delete(path);
File.WriteAllBytes(path, bytes);
Process process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = path,
UseShellExecute = true
}
};
process.Start();
process.WaitForExit();
}
}
}
La seule chose qui m'a vraiment donné mal à la tête était de référencer le System.Data.SqlServerCe.dll - il ne voulait tout simplement pas IlMerge, alors je l'ai plutôt chargé à la demande, dans mon principal:
AppDomain.CurrentDomain.AssemblyResolve += RedistHelper.OnCurrentDomainOnAssemblyResolve;
Je ne sais pas si quelque chose a changé ou non. Mais avec le dernier package de nuget SQL Server CE, les manifestes d'application ne sont plus nécessaires. Vous obtiendrez deux ensembles de binaires: x86 et AMD64. Copiez-les simplement dans votre dossier cible sous le sous-répertoire x86 et/ou AMD64.
|--Your App Dir
|--x86 (x86 sql ce binaries)
|--AMD64 (AMD64 sql ce binaries)
Et vous êtes prêt à partir. Il semble que System.Data.SqlCe.dll puisse rechercher et charger automatiquement les fichiers binaires natifs. Vous pouvez également les déployer dans le répertoire de l'application si votre application n'est ciblée que pour une seule plate-forme.