C# SQL Server CE不支持带EF的ExecuteSQLCommand?

C# SQL Server CE不支持带EF的ExecuteSQLCommand?,c#,entity-framework,tsql,sql-server-ce,C#,Entity Framework,Tsql,Sql Server Ce,我一直在用VS2015开发一个C#WPF项目,使用SQL Server Express LocalDb和实体框架。我为数据库构建了一个自定义种子程序,它从Excel文件中读取测试数据,将Excel数据简单地组合成一个命令字符串,并使用context.database.ExecuteSQLCommand插入 现在,我正在考虑使用SQL Server Compact Edition 4.0启动该项目,但我发现该命令不再有效。我是否必须使用SqlCeConnection和SqlCeCommand再次编

我一直在用VS2015开发一个C#WPF项目,使用SQL Server Express LocalDb和实体框架。我为数据库构建了一个自定义种子程序,它从Excel文件中读取测试数据,将Excel数据简单地组合成一个命令字符串,并使用
context.database.ExecuteSQLCommand
插入

现在,我正在考虑使用SQL Server Compact Edition 4.0启动该项目,但我发现该命令不再有效。我是否必须使用
SqlCeConnection
SqlCeCommand
再次编写上传程序,或者我遗漏了什么

另外,我从某个地方了解到,使用EF可以切换SQL提供程序,代码不需要其他更改。今后我还会有更多惊喜吗

uploader命令的示例:

string cmd = "INSERT INTO Venues(Name, City, Telephone) Values ('X','Y','Z')"
context.Database.ExecuteSqlCommand(cmd);
错误:

分析查询时出错。[令牌行编号=2,令牌行偏移量=1,令牌出错=插入]

这不仅仅是一个测试问题,因为我想在生产版本中也包括这个上传程序,以便快速插入主数据(例如员工列表)

编辑:上传程序代码。如果这可以在不使用原始SQL的情况下完成,那么这也是一个很好的解决方案。

这将在Excel工作表(以实体命名)和列(第一行具有属性名称)以及第2行->第n行(数据)之间循环。这可以处理Excel限制范围内基本上任何数量的数据的上传。关键是代码不知道实体(可能也可以参数化DataContext)。代码可能不是最优的,因为我只是一个初学者,但对我来说是有效的,除了SQL CE。编辑以适应CE不是一个大问题,但我想寻求可能更好的方法

public static class ExcelUploader
{
    static ArrayList data;
    static List<string> tableNames;

    public static string Upload(string filePath)
    {
        string result = "";
        data = new ArrayList();
        tableNames = new List<string>();
        ArrayList upLoadData = ReadFile(filePath);
        List<string> dataList = ArrayListToStringList(upLoadData);

        using (var db = new DataContext())
        {
            using (var trans = db.Database.BeginTransaction())
            {
                try
                {
                    foreach (var cmd in dataList)
                    {
                        Console.WriteLine(cmd);
                        db.Database.ExecuteSqlCommand(cmd);
                    }
                    db.SaveChanges();
                    trans.Commit();
                }
                catch (Exception e)
                {
                    trans.Rollback();
                    result = e.Message;
                    MessageBox.Show(result);
                }
            }
        }
        return result;
    }


    private static ArrayList ReadFile(string fileName)
    {
        List<string> commands = new List<string>();

        var xlApp = new Microsoft.Office.Interop.Excel.Application();
        var wb = xlApp.Workbooks.Open(fileName, ReadOnly: true);
        xlApp.Visible = false;
        foreach (Worksheet ws in wb.Worksheets)
        {
            var r = ws.UsedRange;
            var array = r.Value;
            data.Add(array);
            tableNames.Add(ws.Name);
        }
        wb.Close(SaveChanges: false);
        xlApp.Quit();

        return data;
    }

    private static List<string> ArrayListToStringList(ArrayList arrList)
    {
        List<string> result = new List<string>();

        for(int tableAmount = 0;tableAmount<data.Count;tableAmount++)
        {
            result.Add(ArrayToSqlCommand(arrList[tableAmount] as Array, tableNames[tableAmount]));
        }

        return result;
    }

    private static string ArrayToSqlCommand(Array arr, string tableName)
    {
        int propertyRow = 1;
        int firstDataRow = 2;
        string command = "";

        // loop rows                
        for (int rowIndex = firstDataRow; rowIndex <= arr.GetUpperBound(0); rowIndex++)
        {
            command += "INSERT INTO " + tableName + "(";

            //add column names
            for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
            {
                //get property name
                command += arr.GetValue(propertyRow, colIndex);

                //add comma if not last column, otherwise close bracket
                if (colIndex == arr.GetUpperBound(1))
                {
                    command += ") Values (";
                }
                else
                {
                    command += ", ";
                }
            }

            //add values
            for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
            {
                //get property value
                command += "'" + arr.GetValue(rowIndex, colIndex) + "'";

                //add comma if not last column, otherwise close bracket
                if (colIndex == arr.GetUpperBound(1))
                {
                    command += ");";
                }
                else
                {
                    command += ", ";
                }
            }
            command += "\n";
        }

        return command;
    }

}
公共静态类ExcelUploader
{
静态数组列表数据;
静态列表表名;
公共静态字符串上载(字符串文件路径)
{
字符串结果=”;
数据=新的ArrayList();
tableNames=新列表();
ArrayList upLoadData=ReadFile(文件路径);
List dataList=ArrayListToStringList(上传数据);
使用(var db=new DataContext())
{
使用(var trans=db.Database.BeginTransaction())
{
尝试
{
foreach(数据列表中的var cmd)
{
控制台写入线(cmd);
db.Database.ExecuteSqlCommand(cmd);
}
db.SaveChanges();
trans.Commit();
}
捕获(例外e)
{
trans.Rollback();
结果=e.消息;
MessageBox.Show(结果);
}
}
}
返回结果;
}
私有静态ArrayList读取文件(字符串文件名)
{
List命令=new List();
var xlApp=new Microsoft.Office.Interop.Excel.Application();
var wb=xlApp.Workbooks.Open(文件名,只读:true);
xlApp.Visible=false;
foreach(工作表工作表中的工作表ws)
{
var r=ws.UsedRange;
var数组=r.值;
data.Add(数组);
tableNames.Add(ws.Name);
}
wb.Close(保存更改:false);
xlApp.Quit();
返回数据;
}
私有静态列表ArrayListToStringList(ArrayList arrList)
{
列表结果=新列表();

对于(int tableAmount=0;tableAmount,我提供了两种使用原始SQL查询的方法

初始数据 1) Excel表格 3) 从Excel获取数据 这里我们感兴趣的是从Excel工作表中获取数组。一旦获得数组,我们就可以安全地关闭Excel。代码假定文件“Employees.xlsx”位于可执行文件的旁边

private object[,] GetExcelData()
{
    xlApp = new Excel.Application { Visible = false };
    var xlBook =
        xlApp.Workbooks.Open(System.IO.Path.Combine(
                                 Environment.CurrentDirectory,
                                 "Employees.xlsx"));
    var xlSheet = xlBook.Sheets[1] as Excel.Worksheet;

    // For process termination
    var xlHwnd = new IntPtr(xlApp.Hwnd);
    var xlProc = Process.GetProcesses()
                 .Where(p => p.MainWindowHandle == xlHwnd)
                 .First();

    // Get Excel data: it's 2-D array with lower bounds as 1.
    object[,] arr = xlSheet.Range["A1"].CurrentRegion.Value;

    // Shutdown Excel
    xlBook.Close();
    xlApp.Quit();
    xlProc.Kill();
    GC.Collect();
    GC.WaitForFullGCComplete();

    return arr;
}
现在您可以使用以下方法之一生成查询

选项1.使用ExecuteSqlCommand 使用
ExecuteSqlCommand
时,建议使用参数化查询以避免错误。您可以传递显式创建的
SqlCeParameter
或只传递一个值

private void UseExecuteSqlCommand()
{
    object[,] arr = GetExcelData();

    using (var db = new EmpContext())
    {

        db.Database.Initialize(true);

        int count = 0;
        string sql = "INSERT INTO Venues (Name, City, Telephone) " +
                     "VALUES (@name, @city, @phone);";

        // Start from 2-nd row since we need to skip header
        for (int r = 2; r <= arr.GetUpperBound(0); ++r)
        {
            db.Database.ExecuteSqlCommand(
                sql,
                new SqlCeParameter("@name", (string)arr[r, 1]),
                new SqlCeParameter("@city", (string)arr[r, 2]),
                new SqlCeParameter("@phone", (string)arr[r, 3])
            );

            ++count;
        }

        conn.Close();
        MessageBox.Show($"{count} records were saved.");
    }
}
您还可以对参数使用序号位置,这样可以避免创建参数名称,并使代码更短:

private void UseDbConnection()
{

    object[,] arr = GetExcelData();

    using (var db = new EmpContext())
    {

        db.Database.Initialize(true);

        int count = 0;
        // Take a note - use '?' as parameters
        string sql = "INSERT INTO Venues (Name, City, Telephone) " +
                     "VALUES (?, ?, ?);";

        DbConnection conn = db.Database.Connection;
        conn.Open();
        DbCommand command = conn.CreateCommand();
        command.CommandText = sql;
        command.CommandType = CommandType.Text;

        // Create parameters
        command.Parameters.Add(command.CreateParameter());
        command.Parameters.Add(command.CreateParameter());
        command.Parameters.Add(command.CreateParameter());

        for (int r = 2; r <= arr.GetUpperBound(0); ++r)
        {
            // Access parameters by position
            command.Parameters[0].Value = (string)arr[r, 1];
            command.Parameters[1].Value = (string)arr[r, 2];
            command.Parameters[2].Value = (string)arr[r, 3];
            command.ExecuteNonQuery();
            ++count;
        }

        conn.Close();
        MessageBox.Show($"{count} records were saved.");
    }
}
private void UseDbConnection()
{
对象[,]arr=GetExcelData();
使用(var db=new EmpContext())
{
db.Database.Initialize(true);
整数计数=0;
//记下-使用“?”作为参数
string sql=“插入场馆(名称、城市、电话)”+
“值(?,?);”;
DbConnection conn=db.Database.Connection;
conn.Open();
DbCommand=conn.CreateCommand();
command.CommandText=sql;
command.CommandType=CommandType.Text;
//创建参数
command.Parameters.Add(command.CreateParameter());
command.Parameters.Add(command.CreateParameter());
command.Parameters.Add(command.CreateParameter());

对于(int r=2;r基于JohnyL出色的输入,我能够修改我的代码,使其与SQL Server Express和SQL Server CE一起工作。我将把我的新代码作为答案,因为我必须进一步参数化它,因为我也不能在代码中写入属性名称。但这是一个简单的步骤,一旦我从JohnyL那里得到了这个想法。不是尽管如此,如果数据库写入操作应该包装在DbTransaction中,但这现在起作用了

public static class ExcelUploader
{
    static ArrayList data;
    static List<string> tableNames;
    static List<DbCommand> cmdList = new List<DbCommand>();
    static DbConnection conn;

    public static void Upload(string filePath)
    {
        data = new ArrayList();
        tableNames = new List<string>();
        //get Excel data to array list
        ArrayList upLoadData = ReadFile(filePath);

        using (var db = new DataContext())
        {
            conn = db.Database.Connection;

            //transform arraylist into a list of DbCommands
            ArrayListToCommandList(upLoadData);

            conn.Open();
            try
            {
                foreach (var cmd in cmdList)
                {
                    //Console.WriteLine(cmd.CommandText);
                    cmd.ExecuteNonQuery();
                }
            }
            catch (Exception e)
            {
                var result = e.Message;
                MessageBox.Show(result);
            }
        }

    }

    //opens Excel file and reads worksheets to arraylist
    private static ArrayList ReadFile(string fileName)
    {
        List<string> commands = new List<string>();

        var xlApp = new Microsoft.Office.Interop.Excel.Application();
        var wb = xlApp.Workbooks.Open(fileName, ReadOnly: true);
        xlApp.Visible = false;
        foreach (Worksheet ws in wb.Worksheets)
        {
            var r = ws.UsedRange;
            var array = r.Value;
            data.Add(array);
            tableNames.Add(ws.Name);
        }
        wb.Close(SaveChanges: false);
        xlApp.Quit();

        return data;
    }

    //transforms arraylist to a list of DbCommands
    private static void ArrayListToCommandList(ArrayList arrList)
    {
        List<DbCommand> result = new List<DbCommand>();

        for (int tableAmount = 0; tableAmount < data.Count; tableAmount++)
        {

            ArrayToSqlCommands(arrList[tableAmount] as Array, tableNames[tableAmount]);
        }

    }

    private static void ArrayToSqlCommands(Array arr, string tableName)
    {
        //Excel row which holds property names
        int propertyRow = 1;
        //First Excel row with values
        int firstDataRow = 2;
        string sql = "";

        DbCommand cmd = conn.CreateCommand();

        sql += "INSERT INTO " + tableName + "(";

        //add column names to command text
        for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
        {
            //get property name
            sql += arr.GetValue(propertyRow, colIndex);

            //add comma if not last column, otherwise close bracket
            if (colIndex == arr.GetUpperBound(1))
            {
                sql += ") Values (";
            }
            else
            {
                sql += ", ";
            }
        }

        //add value parameter names to command text
        for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
        {
            //get property name
            sql += "@" + arr.GetValue(propertyRow, colIndex);

            //add comma if not last column, otherwise close bracket
            if (colIndex == arr.GetUpperBound(1))
            {
                sql += ");";
            }
            else
            {
                sql += ", ";
            }
        }

        //add data elements as command parameter values
        for (int rowIndex = firstDataRow; rowIndex <= arr.GetUpperBound(0); rowIndex++)
        {
            //initialize command
            cmd = conn.CreateCommand();
            cmd.CommandText = sql;
            cmd.CommandType = CommandType.Text;

            for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
            {
                //set parameter values
                DbParameter param = null;
                param = cmd.CreateParameter();
                param.ParameterName = "@" + (string)arr.GetValue(propertyRow, colIndex);
                cmd.Parameters.Add(param);
                cmd.Parameters[param.ParameterName].Value = arr.GetValue(rowIndex, colIndex);
            }
            //add command to command list
            cmdList.Add(cmd);

        }

    }
}
公共静态类ExcelUploader
{
静态数组列表数据;
静态列表表名;
静态列表cmdList=新列表();
静态数据库连接;
公共静态无效上载(字符串文件路径)
{
数据=新的ArrayList();
tableNames=新列表();
//将Excel数据获取到数组列表
ArrayList upLoadData=ReadFile(文件路径);
使用(var db=new DataContext())
{
conn=db.Database.Connection;
private void UseDbConnection()
{
    object[,] arr = GetExcelData();

    using (var db = new EmpContext())
    {

        db.Database.Initialize(true);

        int count = 0;
        string sql = "INSERT INTO Venues (Name, City, Telephone) " +
                     "VALUES (@name, @city, @phone);";

        DbParameter param = null;

        DbConnection conn = db.Database.Connection;
        conn.Open();

        DbCommand command = conn.CreateCommand();
        command.CommandText = sql;
        command.CommandType = CommandType.Text;

        // Create parameters

        // Name
        param = command.CreateParameter();
        param.ParameterName = "@name";
        command.Parameters.Add(param);

        // City
        param = command.CreateParameter();
        param.ParameterName = "@city";
        command.Parameters.Add(param);

        // Telephone
        param = command.CreateParameter();
        param.ParameterName = "@phone";
        command.Parameters.Add(param);

        // Start from 2-nd row since we need to skip header
        for (int r = 2; r <= arr.GetUpperBound(0); ++r)
        {
            command.Parameters["@name"].Value = (string)arr[r, 1];
            command.Parameters["@city"].Value = (string)arr[r, 2];
            command.Parameters["@phone"].Value = (string)arr[r, 3];
            command.ExecuteNonQuery();
            ++count;
        }

        conn.Close();
        MessageBox.Show($"{count} records were saved.");
    }
}
private void UseDbConnection()
{

    object[,] arr = GetExcelData();

    using (var db = new EmpContext())
    {

        db.Database.Initialize(true);

        int count = 0;
        // Take a note - use '?' as parameters
        string sql = "INSERT INTO Venues (Name, City, Telephone) " +
                     "VALUES (?, ?, ?);";

        DbConnection conn = db.Database.Connection;
        conn.Open();
        DbCommand command = conn.CreateCommand();
        command.CommandText = sql;
        command.CommandType = CommandType.Text;

        // Create parameters
        command.Parameters.Add(command.CreateParameter());
        command.Parameters.Add(command.CreateParameter());
        command.Parameters.Add(command.CreateParameter());

        for (int r = 2; r <= arr.GetUpperBound(0); ++r)
        {
            // Access parameters by position
            command.Parameters[0].Value = (string)arr[r, 1];
            command.Parameters[1].Value = (string)arr[r, 2];
            command.Parameters[2].Value = (string)arr[r, 3];
            command.ExecuteNonQuery();
            ++count;
        }

        conn.Close();
        MessageBox.Show($"{count} records were saved.");
    }
}
public static class ExcelUploader
{
    static ArrayList data;
    static List<string> tableNames;
    static List<DbCommand> cmdList = new List<DbCommand>();
    static DbConnection conn;

    public static void Upload(string filePath)
    {
        data = new ArrayList();
        tableNames = new List<string>();
        //get Excel data to array list
        ArrayList upLoadData = ReadFile(filePath);

        using (var db = new DataContext())
        {
            conn = db.Database.Connection;

            //transform arraylist into a list of DbCommands
            ArrayListToCommandList(upLoadData);

            conn.Open();
            try
            {
                foreach (var cmd in cmdList)
                {
                    //Console.WriteLine(cmd.CommandText);
                    cmd.ExecuteNonQuery();
                }
            }
            catch (Exception e)
            {
                var result = e.Message;
                MessageBox.Show(result);
            }
        }

    }

    //opens Excel file and reads worksheets to arraylist
    private static ArrayList ReadFile(string fileName)
    {
        List<string> commands = new List<string>();

        var xlApp = new Microsoft.Office.Interop.Excel.Application();
        var wb = xlApp.Workbooks.Open(fileName, ReadOnly: true);
        xlApp.Visible = false;
        foreach (Worksheet ws in wb.Worksheets)
        {
            var r = ws.UsedRange;
            var array = r.Value;
            data.Add(array);
            tableNames.Add(ws.Name);
        }
        wb.Close(SaveChanges: false);
        xlApp.Quit();

        return data;
    }

    //transforms arraylist to a list of DbCommands
    private static void ArrayListToCommandList(ArrayList arrList)
    {
        List<DbCommand> result = new List<DbCommand>();

        for (int tableAmount = 0; tableAmount < data.Count; tableAmount++)
        {

            ArrayToSqlCommands(arrList[tableAmount] as Array, tableNames[tableAmount]);
        }

    }

    private static void ArrayToSqlCommands(Array arr, string tableName)
    {
        //Excel row which holds property names
        int propertyRow = 1;
        //First Excel row with values
        int firstDataRow = 2;
        string sql = "";

        DbCommand cmd = conn.CreateCommand();

        sql += "INSERT INTO " + tableName + "(";

        //add column names to command text
        for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
        {
            //get property name
            sql += arr.GetValue(propertyRow, colIndex);

            //add comma if not last column, otherwise close bracket
            if (colIndex == arr.GetUpperBound(1))
            {
                sql += ") Values (";
            }
            else
            {
                sql += ", ";
            }
        }

        //add value parameter names to command text
        for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
        {
            //get property name
            sql += "@" + arr.GetValue(propertyRow, colIndex);

            //add comma if not last column, otherwise close bracket
            if (colIndex == arr.GetUpperBound(1))
            {
                sql += ");";
            }
            else
            {
                sql += ", ";
            }
        }

        //add data elements as command parameter values
        for (int rowIndex = firstDataRow; rowIndex <= arr.GetUpperBound(0); rowIndex++)
        {
            //initialize command
            cmd = conn.CreateCommand();
            cmd.CommandText = sql;
            cmd.CommandType = CommandType.Text;

            for (int colIndex = 1; colIndex <= arr.GetUpperBound(1); colIndex++)
            {
                //set parameter values
                DbParameter param = null;
                param = cmd.CreateParameter();
                param.ParameterName = "@" + (string)arr.GetValue(propertyRow, colIndex);
                cmd.Parameters.Add(param);
                cmd.Parameters[param.ParameterName].Value = arr.GetValue(rowIndex, colIndex);
            }
            //add command to command list
            cmdList.Add(cmd);

        }

    }
}