Отображение данных Linq с базой данных Ms Access: «Отсутствует точка с запятой (;) в конце оператора SQL». - PullRequest
3 голосов
/ 05 февраля 2011

Я использовал отображение данных Linq с базой данных Ms Access.Я создаю OleDbConnection как обычно и передаю его DataContext.

До сих пор это работало нормально, для извлечения данных из таблиц, основанных на сложных запросах, и даже работы с отношениями для автоматического заполнения спискадочерние объекты в отношении 1-N.

Однако, когда я пытаюсь вставить данные, используя следующий код:

    [Table(Name = "test_table")]
    public class test_item {
        [Column(IsPrimaryKey = true, IsDbGenerated = true)]
        public int field1;
        [Column]
        public int field2;
    }
    public void Test() {
        Table<test_item> tbl = this.GetTable<test_item>();
        test_item x = new test_item();
        x.field2 = 1222;
        tbl.InsertOnSubmit(x);
        this.SubmitChanges();
    }

, я получаю следующую ошибку:

"Missing semicolon (;) at end of SQL statement."
at System.Data.OleDb.OleDbCommand.ExecuteCommandTextErrorHandling(OleDbHResult hr)
at System.Data.OleDb.OleDbCommand.ExecuteCommandTextForSingleResult(tagDBPARAMS dbParams, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommandText(Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteCommand(CommandBehavior behavior, Object& executeResult)
at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
at System.Data.OleDb.OleDbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.OleDb.OleDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader()
at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult)
at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries)
at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
at System.Data.Linq.ChangeDirector.StandardChangeDirector.DynamicInsert(TrackedObject item)
at System.Data.Linq.ChangeDirector.StandardChangeDirector.Insert(TrackedObject item)
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges()
at MyClass.Test() in C:\...\MyClass.cs:line 123

Если я удаляю флаг IsDbGenerated, он не падает, но в этом случае я вынужден указать первичный ключ (x.field1 = 55), но мне бы хотелось, чтобы он назначался автоматически.

Какможно ли избежать этого исключения?

Ответы [ 3 ]

3 голосов
/ 06 февраля 2011

Я видел это :).Похоже, вы спорили о том, что в Linq2SQL отсутствует принудительное использование типов соединений;).Linq2SQL не поддерживается в Access, и хотя большинство запросов на чтение и некоторые запросы на вставку работают из-за схожести Access SQL и TSQL, другие вещи просто нереализуемы, и одна из таких вещей - вставка со столбцами автоматической идентификации.Причина в том, что Linq генерирует два запроса как часть одной и той же команды вставки (один для вставки записи, второй для извлечения вновь сгенерированного идентификатора), и это не совсем подходит для Access.Обходной путь возможен, но довольно уродлив, вам нужно создать подкласс вашего DataContext, а затем создать ВСЕ проблемные методы Insert * (в вашем случае InsertTest_Table), а затем использовать эти методы для выполнения двух последовательных команд внутри одной транзакции

void InsertTest_Table(Test_Table t)
{
    IDbCommand cmd;
    cmd = Connection.CreateCommand();
    cmd.Transaction = this.Transaction;
    cmd.CommandText = "INSERT INTO [Test_Table] ([Field2]) VALUES (@p0)";
    cmd.Parameters.Add(new OleDbParameter("p0", t.field2));
    cmd.ExecuteNonQuery();

    cmd = Connection.CreateCommand();
    cmd.Transaction = this.Transaction;
    cmd.CommandText = "SELECT @@IDENTITY";
    t.field1 = Convert.ToInt32(cmd.ExecuteScalar());
}

Мое предложение, сбросьте Access, если можете, и переключитесь на SQLExpress (даже .SDF лучше) crea

1 голос
/ 06 февраля 2011

Похоже, вы используете Linq to SQL.Linq to SQL предназначен для SQL Server, а не Access.

Почему бы не попробовать Linq to Entities?

Я понимаю, но никогда не делал этого, чтобы в Access был необходимый поставщик ADO.NETтак что должно работать с EF.

0 голосов
/ 21 февраля 2011

Генерация вашего кода ушла от генерации SQL Server, для SQL Server необязательно иметь точку с запятой для MS SQL Server.Попробуйте изменить частичные методы для ваших классов, воспользуйтесь этой ссылкой - http://www.devart.com/linqconnect/docs/ExecuteDynamicMethods.html. Может быть, это может вам помочь.

...