【问题标题】:How to deploy SQL Server Compact Edition 4.0?如何部署 SQL Server Compact Edition 4.0?
【发布时间】:2023-04-05 19:39:01
【问题描述】:

如何部署Microsoft SQL Server Compact 4.0


SQL Server Compact Edition(目前为 4.0 版)是:

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

但是您如何实际部署它?

问题是您不能使用 ADO OLEdb 提供程序,除非它已注册。必须以管理员身份注册 OLEDb 提供程序。这意味着 SQL Server Compact 版本会因非管理员用户而失败。

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/COM 重定向策略显式加载 SQL Server Compact 程序集不受支持,可能会导致在可维护性问题上。有关详细信息,请参阅http://support.microsoft.com/kb/835322http://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

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

在未记录的Program Files 文件夹周围随机拼写我发现了 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

注意:还有一些子文件夹有更多的dll

我尝试将这 7 个 dll 复制到一个文件夹中,并尝试使用 the connection string 打开一个 ADO Connection

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

但它失败了0x80004005 Unspecified error

i tried frobbing the widget, but it grobbed the frobber.

【问题讨论】:

  • 我自己从来没有这样做过,但是文档不清楚吗? msdn.microsoft.com/en-us/library/aa983326(v=vs.110).aspx
  • 在此处查看我的博文:erikej.blogspot.com/2011/02/… 将 SQL Server Compact 4.0 与桌面专用部署和安装项目 (MSI) 结合使用(第 2 部分)
  • 您引用了app.config,我认为这意味着一个 .NET 应用程序。我碰巧正在使用带有 xcopy 部署的本机应用程序。
  • @Pondlife 如何:使用应用程序部署 SQL Server Compact 4.0 数据库页面非常清晰。不幸的是,它也不起作用。他们假设一个 .NET 应用程序,并忽略 OLEDB COM dll sqlceoledb40.dll 所需的注册。
  • 在文档为 gone forever 之前,通过支持它来记录此 post

标签: sql-server-2008 deployment sql-server-ce ado xcopy


【解决方案1】:

我已经创建了解决方案。

SQL Server Compact Edition 由 7 个 dll 组成:

  • sqlceme40.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 对象需要管理 权限 (using a global solution to solve a local problem)。这意味着您的用户会

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

幸运的是,从 2001 年开始使用 Windows XP,Microsoft 解决了这个常见问题:Registration-Free 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 资源构建到您的应用程序中。

请注意,我们依赖于名为 Microsoft.SQLSERVER.CE.4.0 的程序集。我们首先通过创建一个名为

目录来创建这个程序集:

Microsoft.SQLSERVER.CE.4.0

当您部署您的应用程序时,您会将构成此“程序集”的所有 7 个 dll 连同一个特殊的 .manifest 文件一起放入此 Microsoft.SQLSERVER.CE.4.0 子文件夹中:

?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
               

【讨论】:

  • 我的罗宾汉谷仓之旅真是太棒了。有很多更简单的方法:private deployment。您甚至可以更进一步,甚至不将私有程序集和 VC++ 文件复制到您的项目中——只需链接到它们并将 Build Action 设置为 Copy if Newer。
  • @InteXX 所有这些都需要并假定使用 Visual Studio。还有其他构建本机 Win32/64 可执行文件的 IDE。
  • 是的,你是对的。该特定私有部署过程仅适用于 Visual Studio。其他人将需要另一种方式。这是一篇关于免注册 COM 的精彩文章。当我接下来必须这样做时,我会参考它。干得好。
  • 我不确定您在这里使用“Hyperion”。这是您的应用程序的名称还是必须包含的文字?
  • 它无法在 Windows 10 64 位下运行,除非我将以下文件移动到与可执行文件相同的目录中:sqlcese40.dll、sqlceme40.dll、sqlceqp40.dll。
【解决方案2】:

对于 Sql Server Ce 4.0 SP1:

我没有处理所有棘手的部署问题,而是选择将设置文件本身作为 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,所以我在我的 main 中按需加载它:

AppDomain.CurrentDomain.AssemblyResolve += RedistHelper.OnCurrentDomainOnAssemblyResolve;

【讨论】:

    【解决方案3】:

    不确定是否发生了变化。但是使用最新的 SQL Server CE nuget 包,不再需要应用程序清单。您将获得两组二进制文件:x86 和 amd64。只需将它们复制到 x86 和/或 amd64 子目录下的目标文件夹即可。

    |--Your App Dir
       |--x86 (x86 sql ce binaries)
       |--amd64 (amd64 sql ce binaries)
    

    你可以走了。看起来 System.Data.SqlCe.dll 可以自动查找和加载本机二进制文件。如果您的应用仅针对一个平台,您也可以将它们部署在应用目录中。

    【讨论】:

      猜你喜欢
      • 2013-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多