如何部署SQL Server精简版4.0?

我如何部署Microsoft SQL Server Compact 4.0 ?


SQL Server精简版(当前在版本4.0)是:

一个免费的embedded式数据库,软件开发人员可以使用它来构buildWindows桌面应用 它具有很小的占用空间,并支持在应用程序文件夹中私人部署其二进制文件。

但是你怎么实际部署它呢?

  • 微软表示,它可以 部署在应用程序文件夹( ),并支持xcopy部署 。
  • 微软还表示,它不能 部署在应用程序文件夹( ),不支持xcopy部署 。
  • 一些人有使用简单的xcopy部署的例子 ,但他们没有进入完成部署所需的细节

问题是您不能使用ADO OLEdb提供程序,除非它已注册。 注册OLEdb提供程序必须以pipe理员身份完成。 这意味着SQL Server Compact版本将与不是pipe理员的用户一起失败。

SQL Server Compact 4.0附带了一个redist_enu.txt文件:

列出的.exe文件每个都将其封闭的组件安装到目标计算机上的特定位置。 这有助于确保可用性和技术支持。 封装在这些.exe文件中的.dll文件也可以在这个redist.txt文件中单独使用。 但是,这些单独的.dll的分发可能会导致可用性问题。 有关更多详细信息,请参阅http://go.microsoft.com/fwlink/?LinkId=94589

通过BreadCrumb进行专用部署检测:不支持通过Assembly.LoadFrom(),.local文件或使用DLL / COMredirect策略显式加载本地堆栈和显式加载SQL Server Compact Assembly,并且可能导致可维护性问题。 有关更多信息,请参阅http://support.microsoft.com/kb/835322和http://msdn2.microsoft.com/en-us/library/aa375142.aspx

Microsoft SQL Server Compact 4.0

SSCERuntime_x86-CHS.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-CHS.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

但是它不提供有关如何重新分发SQL Server Compact 4.0的任何信息。

随机spellunking无证的Program Files夹我发现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 

注:也有一些儿童文件夹与更多的DLL

我试图复制这7个DLL到一个文件夹,并试图打开一个ADO连接使用连接string :

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

但是它以0x80004005 Unspecified error失败

我试图抖动的部件,但它groberbed frobber。

我已经创build了解决scheme。

SQL Server精简版由7个DLL组成:

  • sqlceme40.dllsqlceme40.dll的本地平面API库(.net System.Data.SqlServerCe.dll程序集是此dll的一个包装)
  • sqlceca40.dll实现EngineReplicationError和一些其他COM对象的COM DLL
  • sqlceoledb40.dll为SSCE实现OLEdb提供程序的COM DLL(允许使用ADO)
  • sqlcese40.dll 未知
  • sqlceqp40.dll 未知
  • sqlcecompact40.dll 未知
  • sqlceer40en.dll 未知

试图简单地运送这些dll的问题是其中两个是COM对象。 COM对象的DLL需要注册 ,例如:

 >regsvr32 sqlceca40.dll >regsvr32 sqlceoledb40.dll 

问题是注册COM对象需要pipe理权限( 使用全局解决scheme来解决本地问题 )。 这意味着你的用户会

  • 必须安装你的应用程序(你不想这样做)
  • 要求你的用户拥有pipe理权限(你不想这样做)

幸运的是,从2001年开始使用Windows XP,Microsoft解决了这个COMmon问题:无注册COM 。

首先,您将声明您的应用程序对SQL Server Compact Edition 4.0具有“依赖性” 。 您可以通过编写程序集清单来完成此操作:

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

您可以将此文件放在您的可执行文件(如Hyperion.exe.manifest旁边 ,也可以将其作为RT_MANIFEST资源构build到您的应用程序中。

请注意,我们有一个称为Microsoft.SQLSERVER.CE.4.0程序集依赖。 我们首先创build一个名为:

Microsoft.SQLSERVER.CE.4.0

当你部署你的应用程序时,你将把包含这个“程序集”的所有7个dll放到这个Microsoft.SQLSERVER.CE.4.0子文件夹中,还有一个特殊的.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 

换句话说,应用程序文件夹包含您的应用程序和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 

您的任务的下一部分是定义Microsoft.SQLSERVER.CE.4.0.manifest文件。 免注册的COM允许清单文件声明所有的COM对象及其clsid。 这花了很多逆向工程。 但是SQL Server Compact Edition 4.0的程序集清单是:

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> 

最后一个问题是,以同样的方式,我们依赖于名为Microsoft.SQLSERVER.CE.4.0的程序集,而SQL Server Compact Edition 4.0则依赖于名为Microsoft.VC90.CRT的程序集。 幸运的是,您安装的SQLCE附带了这个程序集的副本:

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

这意味着最终的目录结构是:

 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 

对于Sql Server Ce 4.0 SP1:

而不是处理所有的部署的坚韧的东西,我只是select包括安装文件本身作为EmbeddedResource我的exe文件,并做了这个小帮手:

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

唯一让我头疼的是引用System.Data.SqlServerCe.dll – 它根本不会IlMerge,所以我按需加载它,在我的主要:

 AppDomain.CurrentDomain.AssemblyResolve += RedistHelper.OnCurrentDomainOnAssemblyResolve;