为什么我的 table 没有被创建?
Why is my table not being created?
我的 Winforms 应用程序中有这段代码,用于在现有数据库中创建 table(我按照 here 所写内容创建的):
private void CreateTables()
{
string connStr = @"Data Source=
(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|
\AYttFM.mdf;Integrated Security=True";
using (var connection = new
System.Data.SqlClient.SqlConnection(connStr))
{
try
{
connection.Open();
using (var command = connection.CreateCommand())
{
StringBuilder sb = new StringBuilder();
sb.Append("CREATE TABLE [dbo].[AssignmentHistory] ");
sb.Append("(");
sb.Append("[Id] INT NOT NULL PRIMARY KEY, ");
sb.Append("[WeekOfAssignment] DATE NOT NULL,");
sb.Append("[TalkType] INT NOT NULL,");
sb.Append("[StudentID_FK] INT NOT NULL, ");
sb.Append("[AssistantID_FK] INT NOT NULL, ");
sb.Append("[CounselPoint] INT NOT NULL");
sb.Append(")");
command.CommandText = sb.ToString();
command.ExecuteNonQuery();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
它 运行 没有抱怨,但没有 table 创建。在 Visual Studio Community 2015 的服务器资源管理器中刷新数据连接及其 Tables 文件夹显示没有 tables。
我在上面的代码中遗漏了什么吗?
注意:出于格式化目的,我在上面的几行中打断了 connStr;实际代码中,connStr全部在一行。
我也无法通过 LINQPad 连接到 .mdf 文件,使用 "Default LINQ to SQL" 和 SQL 服务器提供程序并导航到我项目中的 .mdf 文件(C:\AYttFMApp\AYttFMScheduler\AYttFMScheduler\AYttFM.mdf).它告诉我有一个网络错误:
无论是使用默认服务器“.\SQLEXPRESS”还是将其设置为我的机器名称(这是 [=45= 中 "Servers" 下的唯一条目),我都知道]的服务器资源管理器)。
更新
我重新启动了笔记本电脑,但没有用。 Server Explorer 的数据连接没有显示任何内容,即使在我刷新并尝试添加一个,并将我的机器名称作为服务器名称(毕竟,这就是它所说的服务器在服务器资源管理器中)并选择 .mdf 文件给出我在测试连接时遇到了与 LINQPad 一样的错误。
更新 2
越来越好奇:现在,当我 运行 我的应用程序到达创建 Table 代码时,我收到一条异常消息,指出 AssignmentHistory table 已经创建。然而,如果我查看服务器资源管理器,虽然数据库本身又回来了,但它的 Tables 文件夹仍然是空的。 table怎么可能既有又不存在?
我还在想是不是.mdf文件上设置的属性有误;正如我在下面的评论中所写,这些属性都是默认值:"Copy to Output Directory" 设置为 "Copy Always" 并且 "Build Action" 设置为 "Content" 是否应该更改其中任何一个?
如果代码在行 command.ExecuteNonQuery()
上没有抛出任何异常,那么查询确实完成并且 table 应该在那里。可能是您在使用 LocalDb
时查看了错误的数据库。如果项目已将 .MDF 作为文件包含,并且它被标记为始终复制到目标目录,那么发生的情况是 VS 始终查看未更改的副本并且 Execute 语句始终在调试期间完成,因为未更改的副本是始终替换 运行 时使用的副本。
DataDirectory
指定通常在应用程序启动时分配的位置的占位符。您可以获得实际使用的 .mdf
文件的完整路径,如下所示:
var fullFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.GetData("DataDirectory").ToString(), "AYttFM.mdf");
我已将您的 .mdf
LocalDb 的名称附加到路径的末尾。
您可以添加这行代码并获取文件的路径,然后使用 Visual Studio table 设计器打开此实例。
或者,您可以更改连接字符串并将其硬编码到您的 .mdf 文件的特定实例,保证在您对项目进行构建时不会更改。
编辑 根据您最近的编辑
"Object reference not set to an instance of an object" is what I get
after running the line you provided.
我假设您是手动设置 DataDirectory
位置,抱歉。如果您没有手动设置变量,那么对于 windows 应用程序,默认位置是 .exe 路径。所以代码应该更新为:
var fullFilePath = System.IO.Path.Combine(System.Reflection.Assembly.GetExecutingAssembly().Location.ToString(), "AYttFM.mdf");
这将可能解析为.\yourProjectFolder\debug\bin\AYttFM.mdf
。
The properties are all the defaults: "Copy to Output Directory" is set
to "Copy Always" and "Build Action" is set to "Content"
所以这肯定了我之前写的。每次您进行构建时,它都会将 .mdf 复制到您的 executable 目录,并基本上将数据库刷新到其原始状态。请注意,您可以从 visual studio 执行多个 运行s,这意味着如果所有内容都已经编译并且没有任何更改,则新的 .exe 和内容将不会被重新复制到现有的。这就是为什么您有时会看到异常而有时却没有,这仅取决于 .mdf 是否被覆盖。
Should either of these be changed?
这应该没问题,但这取决于是否可以每次都从头开始。这完全取决于您,以下是您的可用选项:
Copy to Output Directory Property
This property specifies the conditions under which the selected source
file will be copied to the output directory. Select Do not copy if the
file is never to be copied to the output directory. Select Copy always
if the file is always to be copied to the output directory. Select
Copy if newer if the file is to be copied only when it is newer than
an existing file of the same name in the output directory.
如果你想打开 .mdf 文件,你只需在 VS 项目中双击它,它应该在 Server Explorer
-> Data Connections
中打开。没有理由在您的设计器中打开输出文件(.mdf 的副本),我只会编辑您项目中的文件,因为您当前的设置是主文件每次都会覆盖输出文件。
我没有使用 LINQPad 的经验,所以我不能说这个应用程序是否可以附加到 LocalDb 实例。这是关于如何从 previous SO question.
做到这一点的 post
打开SQL 服务器配置管理器并检查您的服务器是否运行ning。如果不是 - 那么 运行 它:
我的 Winforms 应用程序中有这段代码,用于在现有数据库中创建 table(我按照 here 所写内容创建的):
private void CreateTables()
{
string connStr = @"Data Source=
(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|
\AYttFM.mdf;Integrated Security=True";
using (var connection = new
System.Data.SqlClient.SqlConnection(connStr))
{
try
{
connection.Open();
using (var command = connection.CreateCommand())
{
StringBuilder sb = new StringBuilder();
sb.Append("CREATE TABLE [dbo].[AssignmentHistory] ");
sb.Append("(");
sb.Append("[Id] INT NOT NULL PRIMARY KEY, ");
sb.Append("[WeekOfAssignment] DATE NOT NULL,");
sb.Append("[TalkType] INT NOT NULL,");
sb.Append("[StudentID_FK] INT NOT NULL, ");
sb.Append("[AssistantID_FK] INT NOT NULL, ");
sb.Append("[CounselPoint] INT NOT NULL");
sb.Append(")");
command.CommandText = sb.ToString();
command.ExecuteNonQuery();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
它 运行 没有抱怨,但没有 table 创建。在 Visual Studio Community 2015 的服务器资源管理器中刷新数据连接及其 Tables 文件夹显示没有 tables。
我在上面的代码中遗漏了什么吗?
注意:出于格式化目的,我在上面的几行中打断了 connStr;实际代码中,connStr全部在一行。
我也无法通过 LINQPad 连接到 .mdf 文件,使用 "Default LINQ to SQL" 和 SQL 服务器提供程序并导航到我项目中的 .mdf 文件(C:\AYttFMApp\AYttFMScheduler\AYttFMScheduler\AYttFM.mdf).它告诉我有一个网络错误:
无论是使用默认服务器“.\SQLEXPRESS”还是将其设置为我的机器名称(这是 [=45= 中 "Servers" 下的唯一条目),我都知道]的服务器资源管理器)。
更新
我重新启动了笔记本电脑,但没有用。 Server Explorer 的数据连接没有显示任何内容,即使在我刷新并尝试添加一个,并将我的机器名称作为服务器名称(毕竟,这就是它所说的服务器在服务器资源管理器中)并选择 .mdf 文件给出我在测试连接时遇到了与 LINQPad 一样的错误。
更新 2
越来越好奇:现在,当我 运行 我的应用程序到达创建 Table 代码时,我收到一条异常消息,指出 AssignmentHistory table 已经创建。然而,如果我查看服务器资源管理器,虽然数据库本身又回来了,但它的 Tables 文件夹仍然是空的。 table怎么可能既有又不存在?
我还在想是不是.mdf文件上设置的属性有误;正如我在下面的评论中所写,这些属性都是默认值:"Copy to Output Directory" 设置为 "Copy Always" 并且 "Build Action" 设置为 "Content" 是否应该更改其中任何一个?
如果代码在行 command.ExecuteNonQuery()
上没有抛出任何异常,那么查询确实完成并且 table 应该在那里。可能是您在使用 LocalDb
时查看了错误的数据库。如果项目已将 .MDF 作为文件包含,并且它被标记为始终复制到目标目录,那么发生的情况是 VS 始终查看未更改的副本并且 Execute 语句始终在调试期间完成,因为未更改的副本是始终替换 运行 时使用的副本。
DataDirectory
指定通常在应用程序启动时分配的位置的占位符。您可以获得实际使用的 .mdf
文件的完整路径,如下所示:
var fullFilePath = System.IO.Path.Combine(AppDomain.CurrentDomain.GetData("DataDirectory").ToString(), "AYttFM.mdf");
我已将您的 .mdf
LocalDb 的名称附加到路径的末尾。
您可以添加这行代码并获取文件的路径,然后使用 Visual Studio table 设计器打开此实例。
或者,您可以更改连接字符串并将其硬编码到您的 .mdf 文件的特定实例,保证在您对项目进行构建时不会更改。
编辑 根据您最近的编辑
"Object reference not set to an instance of an object" is what I get after running the line you provided.
我假设您是手动设置 DataDirectory
位置,抱歉。如果您没有手动设置变量,那么对于 windows 应用程序,默认位置是 .exe 路径。所以代码应该更新为:
var fullFilePath = System.IO.Path.Combine(System.Reflection.Assembly.GetExecutingAssembly().Location.ToString(), "AYttFM.mdf");
这将可能解析为.\yourProjectFolder\debug\bin\AYttFM.mdf
。
The properties are all the defaults: "Copy to Output Directory" is set to "Copy Always" and "Build Action" is set to "Content"
所以这肯定了我之前写的。每次您进行构建时,它都会将 .mdf 复制到您的 executable 目录,并基本上将数据库刷新到其原始状态。请注意,您可以从 visual studio 执行多个 运行s,这意味着如果所有内容都已经编译并且没有任何更改,则新的 .exe 和内容将不会被重新复制到现有的。这就是为什么您有时会看到异常而有时却没有,这仅取决于 .mdf 是否被覆盖。
Should either of these be changed?
这应该没问题,但这取决于是否可以每次都从头开始。这完全取决于您,以下是您的可用选项:
Copy to Output Directory Property
This property specifies the conditions under which the selected source file will be copied to the output directory. Select Do not copy if the file is never to be copied to the output directory. Select Copy always if the file is always to be copied to the output directory. Select Copy if newer if the file is to be copied only when it is newer than an existing file of the same name in the output directory.
如果你想打开 .mdf 文件,你只需在 VS 项目中双击它,它应该在 Server Explorer
-> Data Connections
中打开。没有理由在您的设计器中打开输出文件(.mdf 的副本),我只会编辑您项目中的文件,因为您当前的设置是主文件每次都会覆盖输出文件。
我没有使用 LINQPad 的经验,所以我不能说这个应用程序是否可以附加到 LocalDb 实例。这是关于如何从 previous SO question.
做到这一点的 post打开SQL 服务器配置管理器并检查您的服务器是否运行ning。如果不是 - 那么 运行 它: