【问题标题】:C# creating a database programmatically with SMOC# 使用 SMO 以编程方式创建数据库
【发布时间】:2013-06-21 09:14:21
【问题描述】:

我正在尝试创建一个数据库,但是一旦创建,我就无法连接到它。

服务器是 Microsoft SQL Server 2008 并使用 .Net 4.5。我们使用 SMO 创建数据库,但我们通常使用Dapper 连接和查询数据库。

这是我到目前为止的代码,它有效:

System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(connectionString);

Microsoft.SqlServer.Management.Smo.Server srv = new Microsoft.SqlServer.Management.Smo.Server(new Microsoft.SqlServer.Management.Common.ServerConnection(con));

var database = new Microsoft.SqlServer.Management.Smo.Database(srv, dbName);

database.Create(false);

database.Roles["db_datareader"].AddMember(???);
database.Roles["db_datawriter"].AddMember(???);
database.Roles["db_backupoperator"].AddMember(???);

srv.Refresh();

注意到??? 了吗?我试过了

System.Environment.UserDomainName + "\\" + System.Environment.UserName

System.Environment.UserName

但它失败(更新)错误Add member failed for DatabaseRole 'db_datareader'. 两个值。

问题是,当我创建数据库时,由于某种原因(使用 Dapper),我无法从同一个程序连接到它。 (更新)我收到错误消息:Cannot open database \"<database_name>\" requested by the login. The login failed.\r\nLogin failed for user '<domain>\\<username>'(其中<database_name> 是数据库名称,<domain> 我的登录域,<username> 我的 Windows 登录)。

我错过了什么吗?我在做正确的事吗?我试过在网上搜索,但似乎没有人以这种方式创建数据库。方法有,应该可以的吧?

** 更新 **

如果我注释 database.Roles["..."].AddMember(...) 行,并在 srv.Refresh() 添加断点,从那里恢复程序可以解决所有问题。

为什么断点可以解决一切?我不能只在生产中破坏程序......也不能在每次创建数据库时破坏程序。

【问题讨论】:

  • 您的意思是,如果您使用 SMO 创建数据库,那么您可以永远使用 Dapper 连接到它?你能用 Dapper 连接到任何个数据库吗?
  • 您在尝试将成员添加到角色时说“失败”,但实际的错误消息是什么?你有没有打印出你传递的字符串,看看它们是不是你认为的那样?
  • @RBarryYoung,当我使用 MSSMS 创建数据库时,我可以连接 Dapper。我的问题是当我使用 SMO 程序创建一个时。
  • 再一次,您是说如果您使用 SMO 创建数据库,那么您可以永远使用 Dapper 连接到它?
  • @RBarryYoung,不,我现在正在更新问题。

标签: c# sql-server-2008


【解决方案1】:

听起来 Dapper 连接问题是 SQL Server 异步执行某些 SMO 操作的问题。很可能,新数据库不会立即为其他用户/连接做好准备,但 SQL Server 需要一些时间来准备它。在“人类时间”(在 SSMS 或断点中)这并不明显,但“程序时间”它太快了,所以您可能需要暂停一下。

可能也是角色AddMember 的问题,但这里有很多地方可能是错误的,我们没有足够的信息来说明。 (具体来说,AddMember 稍后会工作吗?传递的字符串是否正确?)

【讨论】:

  • 我已经尝试让当前线程休眠 1 秒(计算机术语中的 long 时间),但没有任何区别。断点是否完成了我可以以编程方式执行并解决问题的任何特殊操作?
  • @YanickRochon 你也注释掉了AddMember 电话吗?另外,尝试添加Application.DoEvents
  • 我确实评论了AddMemberApplication.DoEvents() 也不起作用。我设法通过调用 database.SetOnline();database.BrokerEnabled = true; then 在当前线程上休眠 3 秒来使其工作。这很奇怪,但它有效。虽然我想知道这是否真的是要走的路。 (顺便说一句:我不会以任何其他方式工作。)
  • @YanickRochon 好吧.SetOnline 是有道理的,尽管我认为.BrokerEnabled 没有必要。
【解决方案2】:

发生这种情况是因为您创建了用户,但没有为该用户创建登录。虽然我不知道确切的语法,但您将不得不创建一个Login。您需要将其LoginType 设置为LoginType.WindowsUser。此外,您可能需要将WindowsLoginAccessType 设置为WindowsLoginAccessType.Grant,并且您需要通过构建一个Credential 来设置NetworkCredential,并使用您想要的用户名。

为此,Login 位于 Management Studio 中 ServerSecurity 节点下,而 User 位于 Security 节点下 Database。两者都需要存在才能访问 SQL Server。

【讨论】:

  • 我在其他地方也读到过,但是你如何在 C# 中实现它呢?你能举个例子吗?此外,我已经尝试执行CREATE LOGINCREATE USER,但我收到奇怪的错误,说提供的用户存在于不同的登录名下......或其他类似的奇怪事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-10
  • 2021-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多