.NET SQL 新表不存在
注意:此问题已解决,但会导致新问题。
我收到此错误:
System.Data.SqlClient.SqlException“无效的对象名称 [表名]”
我正在进行数据库更新以随已部署产品的更新一起发布。新更新的应用程序第一次运行时,数据库更新将运行,它有两个主要阶段。
- 运行脚本 update.sql 以将新表添加到数据库
- 调用一些方法从现有表中复制一些数据以填充新表,并进行一些数学计算/进行一些调整。
第一步完美无缺。每当第二步引用任何新表时,都会引发上述异常。在弹出异常的地方调用的代码在整个应用程序(新版本)中多次使用,并且通常没有问题。如果此代码与旧版本的数据库一起运行(因为它使用的表不存在),人们会期望会发生此问题,但在这种情况下,表刚刚被添加。
更新代码:
internal void Update()
{
RunScript(); //runs the SQL script, adds tables to the db
OtherClass oc = new OtherClass();
oc.PrepData(); //no error, just makes some minor tweaks to existing table
oc.CopyData(); //throws exception, none of the new tables appear to exist
oc.AdjustData(); //manipulates the data in the new table, probably throws exception but currently unreachable
}
public class OtherClass
{
private AppEntities db;
public OtherClass()
{
db = new AppEntities();
//other constructor activity
}
internal void CopyData()
{
foreach(DataItem di in db.DataItems) //This throws the exception (with any of the new tables)
{
}
}
}
如上所示,在将表添加到数据库之后初始化的实体集抛出异常,但它仍然不承认其中任何一个存在。
有人遇到过这样的事情吗?有办法解决吗?
更新:
我发现了一些东西,我认为这一定是问题所在。 OtherClass
中的 AppEntities db
声明已更改为 private AppEntities db = new AppEntities();
,并且不再在构造函数,导致它在脚本运行之前创建。不幸的是,解决这个问题仍然会产生同样的问题。
更新:
为了确保数据上下文了解新表,我更改了运行脚本的方式。
以前(针对数据库正确执行的脚本,应用程序找不到新表):
StreamReader sr = new StreamReader(File.Open(String.Format("{0}/Scripts/CURRENTVERSION.sql", AppDomain.CurrentDomain.BaseDirectory), FileMode.Open));
string UpdateScript = sr.ReadToEnd();
sr.Close();
//Here connectionstring was the database's connection taken from the .edmx file and trimmed of arguments that caused exceptions as invalid
SqlConnection connection = new SqlConnection(connectionstring);
SqlCommand command = new SqlCommand(UpdateScript);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
当前:
StreamReader sr = new StreamReader(File.Open(String.Format("{0}/Scripts/CURRENTVERSION.sql", AppDomain.CurrentDomain.BaseDirectory), FileMode.Open));
string UpdateScript = sr.ReadToEnd();
sr.Close();
System.Data.Common.DbCommand command = db.Connection.CreateCommand();
command.CommandText = UpdatScript;
//command.CommandText = @UpdateScript;
db.Connection.Open();
command.ExecuteNonQuery();
我已经尝试了注释行和未注释行(带/不带@),但它声称每行都存在语法错误script(与第一个方法完美执行的脚本相同)。 db.Connection.Close();
更新:
使用这个问题和答案,我能够使用 AppEntities 连接成功执行 SQL 脚本,并且这些表确实出现在数据库中。但是,AppEntities(脚本运行后初始化的类的对象)仍然会抛出无效对象名称的异常。
有没有办法强制数据上下文在运行时从数据库更新自身?
更新(含解决方案):
深入研究 AppEntities(按照 Chris Lively 的建议)是一件非常令人头疼的事情,但它确实让我也深入研究了一些配置文件。在那里,我发现新表被映射为单数名称,而不是复数名称(TableForEntity
而不是 TableForEntities
),以前它们是复数名称(当它起作用了)。旧表也都是复数。此处将新表更改为复数会导致各种错误,因此我最终只是更改 SQL 脚本以用单数命名它们。令人惊讶的是,这有效。
考虑到以复数形式命名它们的 SQL 脚本是根据实际工作的数据库自动生成的(它们以复数形式命名),为什么要更改命名工作呢?如果有的话,这应该导致它解决的问题。
NOTE: This issue has been resolved, but lead to a new question.
I'm getting this error:
System.Data.SqlClient.SqlException "Invalid object name [tablename]"
I'm working on a DB update to ship with an update to a deployed product. The first time the newly updated application runs, the database update runs, and it has two primary stages.
- Run script update.sql to add new tables to the database
- Call some methods to copy some data from existing tables to popuplate the new tables, and do some math/make some adjustments.
Step one works flawlessly. Step two throws the exception above whenever it references any of the new tables. The code called where the exception pops up is used several times throughout the (new version of the)application, and is generally fine. One would expect that this problem would happen if this code ran with the old version of the database (since the tables it uses don't exist), but in this case, the tables have just been added.
Update code:
internal void Update()
{
RunScript(); //runs the SQL script, adds tables to the db
OtherClass oc = new OtherClass();
oc.PrepData(); //no error, just makes some minor tweaks to existing table
oc.CopyData(); //throws exception, none of the new tables appear to exist
oc.AdjustData(); //manipulates the data in the new table, probably throws exception but currently unreachable
}
public class OtherClass
{
private AppEntities db;
public OtherClass()
{
db = new AppEntities();
//other constructor activity
}
internal void CopyData()
{
foreach(DataItem di in db.DataItems) //This throws the exception (with any of the new tables)
{
}
}
}
As shown above, the exception is thrown by an entity set that is initialized after the tables are added to the database, yet it still does not acknowledge that any of them exist.
Has anyone encountered anything like this? Is there a way around it?
UPDATE:
I've discovered something, which I thought must be the problem. The declaration of AppEntities db
in OtherClass
had been changed to private AppEntities db = new AppEntities();
, and it was no longer initialized in the constructor, resulting in it being created before the script is run. Unfortunately, fixing this still yields the same issue.
UPDATE:
In order to assure the data context knows about the new table, I've altered the way I run the script.
Previously (properly executed script against database, application can't find new tables):
StreamReader sr = new StreamReader(File.Open(String.Format("{0}/Scripts/CURRENTVERSION.sql", AppDomain.CurrentDomain.BaseDirectory), FileMode.Open));
string UpdateScript = sr.ReadToEnd();
sr.Close();
//Here connectionstring was the database's connection taken from the .edmx file and trimmed of arguments that caused exceptions as invalid
SqlConnection connection = new SqlConnection(connectionstring);
SqlCommand command = new SqlCommand(UpdateScript);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
Currently:
StreamReader sr = new StreamReader(File.Open(String.Format("{0}/Scripts/CURRENTVERSION.sql", AppDomain.CurrentDomain.BaseDirectory), FileMode.Open));
string UpdateScript = sr.ReadToEnd();
sr.Close();
System.Data.Common.DbCommand command = db.Connection.CreateCommand();
command.CommandText = UpdatScript;
//command.CommandText = @UpdateScript;
db.Connection.Open();
command.ExecuteNonQuery();
I've tried both the commented and un-commented lines (with/without the @), but it claims a syntax error on every line in the script (which is the same script the first method executes flawlessly).
db.Connection.Close();
UPDATE:
Using this question and answer, I was able to successfully execute the SQL script using the AppEntities connection, and the tables did appear in the database. However, AppEntities (an object of the class initialized after the script has run) still throws the exception of invalid object name.
Is there a way to force the data context to update itself from the database at runtime?
UPDATE (with solution):
Digging into AppEntities (as per Chris Lively's suggestion) was a huge headache, but it did lead me to digging into some of the config files as well. It was there I found that the new tables were being mapped to with a singular name, rather than plural (TableForEntity
rather than TableForEntities
), where previously they had been plural (when it worked). The old tables were all plural as well. Changing the new tables to plural here caused all sorts of errors, so I ended up just changing the SQL script to name them in the singular. Surprisingly, this worked.
Considering the SQL script which named them in the plural was autogenerated based on a database that actually worked (where they were named plurally), why should changing the naming work? If anything, that should cause the problem it fixed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不确定 AppEntities 是什么,但我非常有信心它不会反映新数据库的结构。
我猜测它是某种形式的生成代码,纯粹基于数据库的初始版本,并且尚未重新编码(sp?)来保存有关新表的信息。因此,出现错误。
这也可以解释为什么当您在运行之前创建了表时应用程序仍然在同一位置失败。
总而言之,调查 AppEntities 并弄清楚它到底是如何工作的。
I'm not sure what AppEntities is but I'm pretty confident that it does not reflect the structure of your new database.
I'm going to take a guess that it is some form of generated code that is based purely on the initial version of the database and has not been recodegen'd (sp?) to hold information about the new tables. Hence, the error.
This would also explain why the application still fails at that same location when you have created the tables before it even runs.
To sum up, investigate AppEntities and figure out exactly how that thing works.