DacPac在导出或导入时排除用户和登录

时间:2014-02-20 19:30:07

标签: c# sql-server database cross-domain dacpac

我正在做一些自动化,并且正在将一些10-15个旧的,古怪的脚本重写为一个单一且简单的单元,其中包括:

  1. 从生产环境中的MsSql2012导出数据库方案
  2. 在开发环境中将数据库方案导入MsSql2012
  3. 我是使用 Microsoft.SqlServer.Dac 执行此操作,我可以在其中导出/导入dac包。

    它工作得很好:),但在完成我的所有TDD和测试之后,现在是真实的时间了,结果我完全错过了我的工作中有2个域。

    这意味着当我在开发环境中导入dacpac时出现错误,因为我们的2个域没有完全双向信任,当然数据库也有来自两个域的用户。特别是生产域用户。 我可以看到3个可行的解决方案:

    1. 在环境之间获得完全信任。但由于我工作中实施的高安全性,这种情况不会发生。
    2. 在没有用户的情况下导入dacpac。
    3. 在没有用户的情况下导出到dacpac。
    4. 我已阅读文档(当然模糊不清),试图找到一组可以实现2)或3)的选项。我已经测试了很多组合,但没有一个可以工作。 dac pac导入不断尝试创建用户并失败,因为无法在开发环境中验证生产用户。

      我使用Deploy and Extract导出/导入。 可以在这里找到不同的选项:

      1. 提取:http://technet.microsoft.com/en-us/library/microsoft.sqlserver.dac.dacextractoptions.aspx
      2. 部署:http://technet.microsoft.com/en-us/library/microsoft.sqlserver.dac.dacdeployoptions.aspx
      3. 我找不到任何组合作品,我甚至阅读过帖子,表明它是DacPac中的一个错误。但我不确定。 我现在正在研究的最后一个选项是使用GenerateScript方法,希望能够强制排除用户/登录,但我担心它也无法正常工作。见(http://technet.microsoft.com/en-us/library/hh753526.aspx)。

        问题: 如何在导出或导入中从我的dacpac中排除用户/登录?

        更新

        当前提取设置:

        IgnoreUserLoginMappings = true,
        VerifyExtraction = false,
        

        当前部署设置:

        CreateNewDatabase = true,
        DeployDatabaseInSingleUserMode = true,
        DisableAndReenableDdlTriggers = true,
        IgnoreUserSettingsObjects = true,
        

        更新

        到目前为止,所有事情都指向一个难看的解决方案。

        I can generate a deploy script using DacServices. 
        Then i can parse the script (Remove logins etc).
        Then write the result to a file.
        And then call SQLCMD in an external process given it the generated and parsed file. 
        Finally i must evaluate the result from the SQLCMD process.
        

        使用SQLCMD的原因是生成的脚本显然不是纯tsql,而是使用东西作为':setvar',只有SQLCMD可以处理,据我所知。来吧MS ...

        如果有人知道在C#中更好的方法,或者知道DacPac程序集的错误修复/更新,请分享。 :)

        更新

        我发现像IgnorePartitionSchemes这样的东西也行不通。似乎名称空间Microsoft.SqlServer.Dac,不仅仅是一点点,而是非常错误或缺乏实现。

4 个答案:

答案 0 :(得分:5)

我设法通过以下部署dacpac文件解决了这个问题。重要的设置是ExcludeObjectTypes

const string connectionString = @"Data Source=(LocalDB)\MSSQLLocalDB...";
var dacServices = new DacServices(connectionString);

// show deployment in the output window.
dacServices.Message += (o, args) => Debug.WriteLine(args.Message);
dacServices.ProgressChanged += (o, args) => Debug.WriteLine(args.Status);

// load the file.
var dacpac = DacPackage.Load("file.dacpac");
var options = new DacDeployOptions
    {
         IgnorePermissions = true,
         IgnoreUserSettingsObjects = true,
         IgnoreLoginSids = true,
         IgnoreRoleMembership = true,

         // THIS IS THE MAGIC SETTING THAT FINALLY WORKED.
         ExcludeObjectTypes = new[] { 
             ObjectType.Users,
             ObjectType.Logins,
             ObjectType.RoleMembership }
    };
dacServices.Deploy(
    dacpac,
    "MyDbName",
    true,
    options);

答案 1 :(得分:1)

在部署期间,重要的设置是“IgnoreUserSettingsObjects”。这将忽略用户,用户 - > login和user->架构关系。将其设置为true应该是实现这一目标的主要方法。

在提取时,您还可以将DacExtractOptions.IgnoreUserLoginMappings设置为true。在这种情况下,不包括user->登录映射,但看起来在部署时忽略用户更为重要。这意味着您需要在部署后运行脚本以确保存在正确的用户。

答案 2 :(得分:0)

我正在努力解决类似的问题。 DACPAC只是一个zip存档,其中包含3个XML文件。我找到了dacpac manipulation tool的源代码,并对其进行了修改以剥离用户和登录DACPAC。

答案 3 :(得分:0)

我们处理此问题的方法是简单地排除包含敏感安全信息的表,然后使用通用信息重新插入它们。 DacServices.ExportBacpac方法有一个重载,它包含要包含的表列表;因此,您可以创建一个不包含要跳过的表的列表。事实证明,它将包括表,它只是忽略数据。因此,我们使用它来,例如,从prod中获取bacpac,然后将其导入到本地开发机器(由于此命令以编程方式跳过敏感数据而已被清理);然后我们运行一些插入脚本来填充用户表,例如使用具有通用密码的全局管理员用户。请参阅此处带有表格列表的重载:https://msdn.microsoft.com/en-us/library/microsoft.sqlserver.dac.dacservices.exportbacpac(v=sql.120).aspx