.NET/SQLite. Вставка родительской/дочерней записи; как получить внешний ключ?

Я использую VS 2008 (C#) и SQLite через поставщика ADO.NET 2.0 (проект SourceForce).

База данных, используемая приложением, содержит таблицы данных «сотрудники» (родительский) и «employmentHistory» (дочерний). Предполагается, что таблицы данных «eploymentHistory» содержат все рабочие контракты для любого данного сотрудника с 1-го дня (например, продвижение по службе создаст новый контракт).

К сожалению, SQLite не поддерживает внешние ключи, поэтому я должен сам позаботиться о согласованности данных.

База данных EmploymentHistory содержит столбцы "id INTEGER PRIMARY KEY NOT NULL, employeeID INTEGER..." Таким образом, очевидно, employeeID будет ссылаться на employee.ID, первичный ключ в таблице сотрудников. Он определяет, ЧЬИМ это контракт.

Я пишу метод для добавления нового сотрудника. У всех будет хотя бы один контракт (первый), поэтому добавление нового сотрудника связано с добавлением контракта.

Вот метод:

internal static void AddNewEmployee(Employee e, ContractChange c)
    {
        SQLiteCommandBuilder builder = new SQLiteCommandBuilder(adapter);
        var insert = new SQLiteCommand(connection);
        insert.CommandText = @"INSERT INTO employees VALUES ( null, @firstName, @lastName, @phone, @mobile, null, null, ";
        insert.CommandText+= @"@birthDate, @sex, @address, @nin, null, null); ";
        insert.Parameters.AddWithValue("firstName", e.info.name);
        insert.Parameters.AddWithValue("lastName", e.info.surname);
        insert.Parameters.AddWithValue("phone", e.info.phone);
        insert.Parameters.AddWithValue("mobile", e.info.mobile);

        insert.Parameters.AddWithValue("birthDate", e.info.DOB);
        insert.Parameters.AddWithValue("sex", e.info.sex);
        insert.Parameters.AddWithValue("address", e.info.address);
        insert.Parameters.AddWithValue("nin", e.info.NIN);

        insert.CommandText += @"INSERT INTO employmentHistory VALUES ( null, null, @startDate, 'true', @position, @contractHrs, ";
        insert.CommandText += @"@holidayAllowance, @comments, null); ";
        insert.Parameters.AddWithValue("startDate", c.date);
        insert.Parameters.AddWithValue("position", (int)c.role);
        insert.Parameters.AddWithValue("contractHrs", (int)c.contractHrs);
        insert.Parameters.AddWithValue("holidayAllowance", c.holidayAllowance);
        insert.Parameters.AddWithValue("comments", c.comments);                        

        DataTable employees = dataset.Tables[0];
        var datarowEmp = employees.NewRow();
        datarowEmp = e.ToDataRow(datarowEmp);
        employees.Rows.Add(datarowEmp);

        DataTable employmentHistory = dataset.Tables[1];
        var datarowContract = employmentHistory.NewRow();
        datarowContract = c.ToDataRow(datarowContract);
        employmentHistory.Rows.Add(datarowContract);

        adapter.UpdateCommand = insert;
        adapter.InsertCommand = insert;
        adapter.SelectCommand = new SQLiteCommand("SELECT * FROM employees; SELECT * FROM employmentHistory;", connection);
        adapter.Update(dataset);


    }

Поэтому я подумал, что установим идентификатор сотрудника «вручную» с помощью быстрого обновления. Но - как я узнаю, какой идентификатор был присвоен сотруднику, которого я только что добавил???

Удивительно (для меня), даже после того, как SQLiteDataAdapter обновил данные (я установил точку останова в самом конце метода), этой информации все еще нет в наборе данных. Поле по-прежнему пустое. И все же SQLite в какой-то момент присваивает уникальный номер, поскольку исключения не выдаются, и сотрудники действительно получают первичные ключи (я видел базу данных в браузере баз данных SQLite).

Так что я не могу сделать это автоматически, и я не могу сделать это вручную - как я должен обеспечить согласованность базы данных? :(


person Konrad Morawski    schedule 30.01.2010    source источник
comment
К вашему сведению, пол считается более подходящим, чем пол   -  person Amirshk    schedule 31.01.2010


Ответы (1)


См. last_insert_rowid.

Вы можете реализовать это в одной строке:

cmd.CommandText = "INSERT INTO .. VALUES(..);SELECT last_insert_rowid() AS [ID]";
strId = cmd.ExecuteScalar().ToString()

Обновление:

Вы также можете включить две вставки в одну транзакцию, чтобы в случае сбоя одной из них можно было откатить всю вставку и предотвратить повреждение данных в базе данных.

person Amirshk    schedule 30.01.2010
comment
Ну, я проверил, и на самом деле это работает так же просто, как в: ВСТАВЬТЕ В ЗНАЧЕНИЯ истории занятости ( null, last_insert_rowid () ... но да, я понимаю, что last_insert_rowid () вернет 0, если добавление сотрудника по какой-либо причине пойдет не так, тогда в лучшем случае Я получаю осиротевшие записи, спасибо за помощь! - person Konrad Morawski; 31.01.2010