Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何以编程方式确定SQL Server CE数据库中是否存在表?_C#_Sql Server Ce_Compact Framework_Windows Ce_Windows Embedded Compact - Fatal编程技术网

C# 如何以编程方式确定SQL Server CE数据库中是否存在表?

C# 如何以编程方式确定SQL Server CE数据库中是否存在表?,c#,sql-server-ce,compact-framework,windows-ce,windows-embedded-compact,C#,Sql Server Ce,Compact Framework,Windows Ce,Windows Embedded Compact,当我的.sdf文件中只有一个表时,此代码运行良好: const string sdfPath = @"\Program Files\duckbilled\Platypus.sdf"; string dataSource = string.Format("Data Source={0}", sdfPath); if (!File.Exists(sdfPath)) { using (var engine = new SqlCeEngine(dataSource)) {

当我的
.sdf
文件中只有一个表时,此代码运行良好:

const string sdfPath = @"\Program Files\duckbilled\Platypus.sdf";
string dataSource = string.Format("Data Source={0}", sdfPath);

if (!File.Exists(sdfPath))
{
    using (var engine = new SqlCeEngine(dataSource))
    {
        engine.CreateDatabase();
    }
    using (var connection = new SqlCeConnection(dataSource))
    {
        connection.Open();
        using (var command = new SqlCeCommand())
        {
            command.Connection = connection;
            command.CommandText =
                "CREATE TABLE Platydudes (Id int NOT NULL, BillSize smallint NOT NULL, Description nvarchar(255)";
            command.ExecuteNonQuery();
        }
    }
}
…但现在我需要知道的不是数据库文件(
Platypus.sdf
)是否存在,而是该表/文件中是否存在特定的表(例如
Platydudes
)。有办法确定吗

更新 查询中的“IF NOT EXISTS”子句导致运行时异常。此代码:

using (var connection = new SqlCeConnection(dataSource))
{
    connection.Open();
    using (var command = new SqlCeCommand())
    {
        command.Connection = connection;
        command.CommandText = "IF NOT EXISTS( SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'InventoryItems') " +
            "CREATE TABLE InventoryItems (Id nvarchar(50) NOT NULL, PackSize smallint NOT NULL, Description nvarchar(255), DeptDotSubdept numeric, UnitCost numeric, UnitList numeric, UPCCode nvarchar(50), UPCPackSize smallint, CRVId int);";
        command.ExecuteNonQuery();
    }
}
…导致引发此异常:分析查询时出错。[令牌行编号=1,令牌行偏移量=1,令牌出错=IF]

因此,查询解析器显然不需要“IF”业务。是否有其他方法仅在表不存在时创建该表?或者每次我都应该先删除表,然后重新创建它?瞧,我应该这样做吗:

using (var connection = new SqlCeConnection(dataSource))
{
    connection.Open();
    using (var command = new SqlCeCommand())
    {
        command.Connection = connection;
        command.CommandText = "DELETE InventoryItems";
        command.ExecuteNonQuery();
    }
    using (var command = new SqlCeCommand())
    {
        command.Connection = connection;
        command.CommandText = "CREATE TABLE InventoryItems (Id nvarchar(50) NOT NULL, PackSize smallint NOT NULL, Description nvarchar(255), DeptDotSubdept numeric, UnitCost numeric, UnitList numeric, UPCCode nvarchar(50), UPCPackSize smallint, CRVId int);";
        command.ExecuteNonQuery();
    }
}
?

更新2 在第一次更新中回答我的问题:不!如果这样做,则在第二次调用.ExecuteNonQuery()时会得到“指定的表已经存在”

更新3 针对Shiva对我的回答的评论:

这(重用命令对象)以同样的方式失败(“表已存在”):


如果要检查表是否存在,必须使用
Table\u SCHEMA

IF (EXISTS (SELECT * 
             FROM INFORMATION_SCHEMA.TABLES 
             WHERE TABLE_SCHEMA = 'TheSchema' 
             AND  TABLE_NAME = 'TheTable'))
BEGIN
--Do Stuff
END

根据湿婆的回答,我会这样做:

if (!File.Exists(sdfPath))
{
    using (var engine = new SqlCeEngine(dataSource))
    {
        engine.CreateDatabase();
    }
}

using (var connection = new SqlCeConnection(dataSource))
{
    connection.Open();
    using (var command = new SqlCeCommand())
    {
        command.Connection = connection;
        command.CommandText ="IF NOT EXISTS( SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Platydudes') " 
                           + "CREATE TABLE Platydudes (Id int NOT NULL, BillSize smallint NOT NULL, Description nvarchar(255) )";
        command.ExecuteNonQuery();
    }
}
public bool TableExists(SqlCeConnection connection, string tableName)
{
    using (var command = new SqlCeCommand())
    {
        command.Connection = connection;
        var sql = string.Format(
                "SELECT COUNT(*) FROM information_schema.tables WHERE table_name = '{0}'", 
                 tableName);
        command.CommandText = sql;
        var count = Convert.ToInt32(command.ExecuteScalar());
        return (count > 0);
    }
}
…根据每个表(鸭嘴兽、鸭嘴兽和c)的需要重复“使用(var连接=…”部分

更新 使用ctacke的代码,我现在有:

public static void ConditionallyCreateTables()
{
    const string sdfPath = @"\Program Files\duckbilled\Platypus.sdf";
    string dataSource = string.Format("Data Source={0}", sdfPath);

    if (!File.Exists(sdfPath))
    {
        using (var engine = new SqlCeEngine(dataSource))
        {
            engine.CreateDatabase();
        }
    }
    using (var connection = new SqlCeConnection(dataSource))
    {
        connection.Open();
        using (var command = new SqlCeCommand())
        {
            command.Connection = connection;

            if (!TableExists(connection, "InventoryItems"))
            {
                command.CommandText = "CREATE TABLE InventoryItems (Id nvarchar(50) NOT NULL, PackSize smallint NOT NULL, Description nvarchar(255), DeptDotSubdept numeric, UnitCost numeric, UnitList numeric, UPCCode nvarchar(50), UPCPackSize smallint, CRVId int);";
                command.ExecuteNonQuery();
            }

            if (!TableExists(connection, "Departments"))
            {
                command.CommandText = "CREATE TABLE Departments (Id int NOT NULL, DeptNum int NOT NULL, DepartmentName nvarchar(255))";
                command.ExecuteNonQuery();
            }

            if (!TableExists(connection, "Subdepartments"))
            {
                command.CommandText = "CREATE TABLE Subdepartments (Id int NOT NULL, DeptId int NOT NULL, SubdeptId int NOT NULL, DepartmentName nvarchar(255))";
                command.ExecuteNonQuery();
            }

            if (!TableExists(connection, "Redemptions"))
            {
                command.CommandText = "CREATE TABLE Redemptions (Id int NOT NULL, RedemptionId nvarchar(50), RedemptionItemId nvarchar(50), RedemptionName nvarchar(255), RedemptionAmount numeric, RedemptionDept nvarchar(50), RedemptionSubdept nvarchar(50))";
                command.ExecuteNonQuery();
            }
        }
    }
}
更新2 我现在已将其更改为以下格式:

if (TableExists(connection, "InventoryItems"))
{
    command.CommandText = "DROP TABLE InventoryItems";
    command.ExecuteNonQuery();
}
command.CommandText = "CREATE TABLE InventoryItems (Id nvarchar(50) NOT NULL, PackSize smallint NOT NULL, Description nvarchar(255), DeptDotSubdept float, UnitCost float, UnitList float, UPCCode nvarchar(50), UPCPackSize smallint, CRVId int);";
command.ExecuteNonQuery();

SQL Compact不太喜欢SQL语句中的逻辑,因此Shiva的答案可能无法通过解析器。不过,他的思路是正确的。您可以分两步完成:

以下是SQL Compact实现的
TableExists
方法:

显然,对于您的情况,它并不完整,但很容易理解。
CurrentTransaction
可以很容易地为空。
GetNewCommandObject
只返回一个新的
SqlCeCommand
实例。
GetConnection
只返回一个新的
SqlCeConnection
实例。DoneWithConnection可以是不,基本上,这些都是在处理ORM支持过多备份存储的事实。您需要的信息的核心是我传入的SQL以及我如何确定真/假返回

我(未经编译器测试)对结果方法的猜测如下:

if (!File.Exists(sdfPath))
{
    using (var engine = new SqlCeEngine(dataSource))
    {
        engine.CreateDatabase();
    }
}

using (var connection = new SqlCeConnection(dataSource))
{
    connection.Open();
    using (var command = new SqlCeCommand())
    {
        command.Connection = connection;
        command.CommandText ="IF NOT EXISTS( SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Platydudes') " 
                           + "CREATE TABLE Platydudes (Id int NOT NULL, BillSize smallint NOT NULL, Description nvarchar(255) )";
        command.ExecuteNonQuery();
    }
}
public bool TableExists(SqlCeConnection connection, string tableName)
{
    using (var command = new SqlCeCommand())
    {
        command.Connection = connection;
        var sql = string.Format(
                "SELECT COUNT(*) FROM information_schema.tables WHERE table_name = '{0}'", 
                 tableName);
        command.CommandText = sql;
        var count = Convert.ToInt32(command.ExecuteScalar());
        return (count > 0);
    }
}
使用数据库帮助器:

var db = Database.Open("MyDatabase");
var sql = @"SELECT Count(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'MyTable'"
var count = db.QueryValue(sql);
if(count.Equals(1)){
    //table exists
}

DELETE inventory items
不会删除表,它只会删除所有行。
DROP table inventory items
会删除表本身。哦,是的,我知道;大脑冻结!我想你应该在
connection.Open();
之前添加
var count=Convert.ToInt32(command.ExecuteScalar());
。我的工作就是这样的。