sql-server-2008 deployment sql-server-ce ado xcopy

sql server 2008 - ¿Cómo implementar SQL Server Compact Edition 4.0?



sql-server-2008 deployment (2)

He creado la solución.

SQL Server Compact Edition se compone de 7 dlls:

  • sqlceme40.dll La biblioteca de API plana nativa no documentada (el ensamblado .NET System.Data.SqlServerCe.dll es un contenedor de este dll)
  • sqlceca40.dll Un dll COM que implementa Engine , Replication , Error y algunos otros objetos COM
  • sqlceoledb40.dll Un dll COM que implementa un proveedor OLEdb para SSCE (que permite el uso de ADO)
  • sqlcese40.dll desconocido
  • sqlceqp40.dll desconocido
  • sqlcecompact40.dll desconocido
  • sqlceer40en.dll desconocido

El problema con tratar de enviar estos dlls es que dos de ellos son objetos COM . Los objetos DLL del objeto COM deben registrarse , por ejemplo:

>regsvr32 sqlceca40.dll >regsvr32 sqlceoledb40.dll

El problema es que registrar un objeto COM requiere privilegios administrativos ( utilizando una solución global para resolver un problema local ). Esto significa que tus usuarios

  • tiene que instalar su aplicación (que no quiere hacer)
  • requiere que sus usuarios tengan permisos administrativos (que no desea hacer)

Afortunadamente, a partir de 2001 con Windows XP, Microsoft resolvió este problema de COMmon: COM sin registro .

Primero, declarará que su aplicación tiene una "dependencia" en SQL Server Compact Edition 4.0. Para ello, crea un manifiesto de ensamblaje:

<?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>

Puede colocar este archivo junto al ejecutable (como Hyperion.exe.manifest ), o puede compilarlo en su aplicación como un recurso RT_MANIFEST .

Tenga en cuenta que tenemos una dependencia contra asamblea llamada Microsoft.SQLSERVER.CE.4.0 . Creamos este ensamblaje primero al crear un directorio llamado:

Microsoft.SQLSERVER.CE.4.0

Cuando implemente su aplicación, colocará los 7 dll que componen este "ensamblado" en esta subcarpeta Microsoft.SQLSERVER.CE.4.0 , junto con un archivo .manifest especial:

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 otras palabras, la carpeta de la aplicación contiene su aplicación y la carpeta 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 siguiente parte de su tarea es definir el archivo Microsoft.SQLSERVER.CE.4.0.manifest . El COM sin registro permite que un archivo de manifiesto declare todos los objetos COM y sus clsid. Esto requirió mucha ingeniería inversa. Pero el manifiesto de conjunto para SQL Server Compact Edition 4.0 es:

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>

El resultado final es que, de la misma manera que tenemos una dependencia en un ensamble llamado Microsoft.SQLSERVER.CE.4.0 , SQL Server Compact Edition 4.0 a su vez tiene una dependencia en un ensamble llamado Microsoft.VC90.CRT . Afortunadamente, su instalación de SQLCE se envía con una copia de este conjunto:

|----Microsoft.VC90.CRT | Microsoft.VC90.CRT.manifest | msvcr90.dll

Esto significa que la estructura de directorio final es:

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

¿Cómo implemento Microsoft SQL Server Compact 4.0 ?

SQL Server Compact Edition (actualmente en la versión 4.0) es:

una base de datos libre e integrada que los desarrolladores de software pueden usar para construir aplicaciones de escritorio de Windows. Tiene una huella pequeña y admite el despliegue privado de sus binarios dentro de la carpeta de la aplicación.

Pero, ¿cómo se implementa realmente?

El problema es que no puede usar el proveedor ADO OLEdb a menos que esté registrado. El registro de un proveedor OLEdb debe hacerse como administrador. Eso significa que la edición SQL Server Compact fallará con usuarios que no sean administradores.

SQL Server Compact 4.0 viene con un archivo redist_enu.txt :

Los archivos .exe enumerados cada uno instala sus componentes adjuntos a una ubicación específica en la computadora de destino. Esto ayuda a garantizar la capacidad de servicio y el soporte técnico. Los archivos .dll incluidos en estos archivos .exe también están disponibles por separado en este archivo redist.txt. Sin embargo, la distribución de estos .dlls separados puede generar problemas de servicio. Para obtener más detalles, consulte http://go.microsoft.com/fwlink/?LinkId=94589

Detección de despliegue privado a través de BreadCrumb: la implementación privada de la pila nativa y la carga explícita de SQL Server Compact Assembly a través de Assembly.LoadFrom (), archivo local o el uso de estrategias de redireccionamiento DLL / COM no son compatibles y pueden generar problemas de mantenimiento. . Para obtener más información, consulte http://support.microsoft.com/kb/835322 y 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

pero no proporciona ninguna información sobre cómo redistribuir SQL Server Compact 4.0.

Aleatoriamente lanzando hechizos alrededor de la carpeta de Program Files indocumentados encontré 7 dlls:

C:/Program Files/Microsoft SQL Server Compact Edition/v4.0/ sqlceoledb40.dll sqlceqp40.dll sqlcese40.dll sqlceca40.dll sqlcecompact40.dll sqlceer40EN.dll sqlceme40.dll

Nota: También hay algunas carpetas secundarias con más dlls

intenté copiar estos 7 dll a una carpeta e intenté abrir una conexión ADO utilizando la cadena de conexión :

Provider=Microsoft.SQLSERVER.CE.OLEDB.4.0;Data Source="store.sdf"

pero falla con 0x80004005 Unspecified error

Intenté prender el widget, pero se apoderó del frobber.


Para Sql Server Ce 4.0 SP1:

En lugar de abordar todos los detalles de la implementación, simplemente opté por incluir los archivos de configuración en mi archivo ejecutable como EmbeddedResource e hice este pequeño ayudante:

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(); } } }

Lo único que realmente me dio un dolor de cabeza fue hacer referencia a System.Data.SqlServerCe.dll, simplemente no IlMerge, así que en su lugar lo cargué a pedido, en mi principal:

AppDomain.CurrentDomain.AssemblyResolve += RedistHelper.OnCurrentDomainOnAssemblyResolve;