English 中文(简体)
如何部署 SQL 服务器压缩版 4. 0 版?
原标题:How to deploy SQL Server Compact Edition 4.0?

我如何部署 ""http://www.microsoft.com/en-us/ download/details.aspx?id=17876"? >Microsoft SQL服务器契约4.0 ?


SQL 服务器压缩版(目前为4. 0版)是:

一个免费的嵌入式数据库, 软件开发者可以用来构建 Windows 桌面应用程序。 它有一个小脚印, 支持在应用程序文件夹中私下部署它的二进制数据库 。

但是,你如何实际部署它?

问题是,您不能使用 ADO OLEDb 提供商, 除非注册。 注册 OLEDB 提供商必须作为管理员。 这意味着 SQL 服务器契约版本将因用户不是管理员而失败 。

SQL SQL 服务器协议4. 0 带有 < code>redist_enu.txt 文件 :

列表. exe 文件 列表中每个文件都将其封闭的部件安装到目的地计算机上的具体位置, 这有助于确保可用性和技术支持。 这些 exe 文件中的.dll 文档也可以单独使用。 但是, 这些单独的.dlls 的分布可能会造成可用性问题。 详情请见 < a href="http://go.microsoft.com/fwlink/?LinkId=94589 > > http://go.microsoft.com/fwlink/??LinkId=94589

通过BreadCrumb的私人部署探测:仅通过议会私下部署本地堆和明确装载SQL服务器契约大会。Loadfrom (),.loadfrom (),.loadfrom files)或使用DLL/COM重置战略得不到支持,并可能导致可使用性问题。详情见ADO连接 使用 :

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

但它以 0x80004005 未知错误 失败

最佳回答

我创造了解决办法。

SQL 服务器压缩版由 7 dlls 组成 :

  • sqlceme40.dll The undocumented, native, flat API library (The .net System.Data.SqlServerCe.dll assembly is a wrapper around this dll)
  • sqlceca40.dll A COM dll that implements Engine, Replication, Error and a few other COM objects
  • sqlceoledb40.dll A COM dll that implements an OLEdb provider for SSCE (allowing the use of ADO)
  • sqlcese40.dll unknown
  • sqlceqp40.dll unknown
  • sqlcecompact40.dll unknown
  • sqlceer40en.dll unknown

试图简单地发运这些浮标的问题在于其中两个是 < 坚固 > COM < /坚固 > 天体。 COM 天体需要 < em > 注册 ,例如:

>regsvr32 sqlceca40.dll
>regsvr32 sqlceoledb40.dll

问题是,注册一个 COM 对象需要 < em> 行政 < / em > 特权 ( 。 这意味着您的用户会使用全球解决方案 < /a > 。

  • have to install your application (which you don t want to do)
  • requires your users to have administrative permissions (which you don t want to do)

幸运的是,从2001年开始,从Windows XP开始,微软公司就解决了这个COMMON问题:Registration-free COM

首先,您将声明您的申请在 SQL 服务器契约第4.0 版上有“ emstrong > ” “ 依赖性” 。

<?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="微软SQSERVER.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>

您可以将此文件 放置在您的可执行文件 旁边( 如 < code> Hyperion. exe.manifest ), 或者您可以将它建在您的应用程序中, 作为 < code> RT_ MANIFEST 资源 。

请注意,我们有一个依赖性, 称为 microsoft.SQLSERVER.CE.4. 0 的组装。 我们首先通过创建“ 强度” 指令 < / 强度” 创建这个组装, 称为 :

微软SQSERVER.CE.4.0

When you deploy your application, you will place all 7 dll s that comprise this "assembly" into this 微软SQSERVER.CE.4.0 subfolder, along with a special .manifest file:

?C:
╰──?Users
   ╰──?Ian
      ╰──?AppData
         ╰──?Local
            ╰──?Hyperion Pro
               ├──?Hyperion.exe
               ├──?Hyperion.exe.manifest
               ╰──?微软SQSERVER.CE.4.0
                  ├──?sqlceme40.dll
                  ├──?sqlceca40.dll
                  ├──?sqlceoledb40.dll
                  ├──?sqlcese40.dll
                  ├──?sqlceqp40.dll
                  ├──?sqlcecompact40.dll
                  ├──?sqlceer40en.dll
                  ╰──?微软SQSERVER.CE.4.0.manifest

In other words, the application folder contains your application, and the 微软SQSERVER.CE.4.0 folder:

 Directory of C:UsersIanAppDataLocalHyperion 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>          微软SQSERVER.CE.4.0
           2 File(s)      1,900,675 bytes
           1 Dir(s)  20,851,503,104 bytes free

The next part of your task is to define the 微软SQSERVER.CE.4.0.manifest file. Registration-free COM allows a manifest file to declare all the COM objects and their clsid s. This took a lot of reverse engineering. But the assembly manifest for SQL Server Compact Edition 4.0 is:

微软SQSERVER.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="微软SQSERVER.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>

The a final gotcha is that, in the same way we have a dependancy on an assembly called 微软SQSERVER.CE.4.0, SQL Server Compact Edition 4.0 in turn has a dependancy on an assembly called Microsoft.VC90.CRT. Fortunately your install of SQLCE ships with a copy of this assembly:

?Microsoft.VC90.CRT
├──?Microsoft.VC90.CRT.manifest 
╰──?msvcr90.dll

这意味着最终目录结构为:

?C:
╰──?Users
   ╰──?Ian
      ╰──?AppData
         ╰──?Local
            ╰──?Hyperion Pro
               ├──?Hyperion.exe
               ├──?Hyperion.exe.manifest
               ╰──?微软SQSERVER.CE.4.0
                  ├──?微软SQSERVER.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 服务器 Ce 4. 0 SP1:

我选择将设置文件本身纳入我的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(
                    @"SOFTWAREMicrosoftMicrosoft SQL Server Compact Editionv4.0ENU");
            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();
            }
        }
    }

唯一让我头痛的是 参照系统 Data. Sql ServerCe.dll- 它根本不会IlMeg,

AppDomain.CurrentDomain.AssemblyResolve += RedistHelper.OnCurrentDomainOnAssemblyResolve;

无法确定某些东西是否已经更改 。 但是, 最新的 SQL 服务器 CE nuget 软件包不再需要应用程序列表 。 您将获得两套二进制二进制的二进制文件: x86 和 amd64 。 请在 x86 和/ 或 amd64 子目录下将它们复制到目标文件夹 。

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

并且您也准备就绪。 看起来System.Data.SqlCe.dll 可以自动找到并装入本地的二进制文件。 您也可以在应用程序目录中安装它们, 如果您的应用程序只针对一个平台 。





相关问题
VS 2008 : How to publish with out DLLs?

I have developed a web application in Visual Studio 2008 and want to publish it in to the production server. I see a publish option there.But its producing files with DLL. I dont want to publish only ...

Apache: Deploying a new site to the server

I have a site currently live on a domain. I would like to switch it to a new site, that is currently in a password protected sub directory on this server. I have a "Site Maintenance in Progress" page....

Appropriate strategy for tagging and hotfixing with git

I was wondering if the strategy I m using for tagging and hotfixing tags (which then I use for deploying rails applications) with git is appropriate. For tagging I just tag a commit of the master ...

Pylons deployment questions

I m a beginner with Pylons and I ve mostly developed on my localhost using the built-in web server. I think it s time to start deployment for my personal blog, I have a Debian Lenny server with ...

Do I want Publish or Release Build in VB.net?

I wrote a little (like 40 lines little) Winforms application with VB.net in Visual Studio 2010. Now I ve released the code as a Google Code project. It s easy for a developer to get the source but I d ...

Need advice on my PHP development solution

Here is how our current php development solution is set up: Each developer work on their local machine. Each developer commit their change to a common SVN server (intranet). A commit hook upload the ...

loading from JAR files during deployment vs development

when i am loading some data into my java program, i usually use FileInputStream. however i deploy the program as a jar file and webstart, so i have to use getRessource() or getRessourceAsStream() to ...

热门标签