Keith Lewis Ответов: 1

Как перезаписать базу данных sqlite?


Я новичок в программировании и пытаюсь сделать небольшую игру в духе серии Football Manager, которая использует базу данных, я использую WPF C# и SQLite.

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

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

Это диалог сохранения и получения пути к файлу и имени файла базы данных, который он создает:


public void SaveName()
      {
          Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog();
          sfd.FileName = "NewDatabase"; // Default file name
          sfd.DefaultExt = ".db3"; // Default file extension
          sfd.Filter = "SQLite Databases (.db3)|*.db3"; // Filter files by extension
          sfd.ShowDialog();
          Variables.dbPath = sfd.FileName;
          Variables.dbName = System.IO.Path.GetFileNameWithoutExtension(Variables.dbPath);
      }


Это моя кнопка "новая игра" :

private void button_Click(object sender, RoutedEventArgs e)
    {
        dbt.SaveName();
        DatabaseTasks.CreateDatabase(Variables.dbName);
        dbt.SetConnection(Variables.dbPath);
        dbt.CreateTables();
        dbt.PopulatePeopleTable();
    }


Это создание таблиц:

  public void CreateTables()
        {
            m_dbConn.Open();

            string ctPeople = "CREATE TABLE people (FirstName VARCHAR(20), LastName VARCHAR(20), Age INT, Strength INT, Agility INT, Dexterity INT, CA INT)";
            SQLiteCommand cmdCTP = new SQLiteCommand(ctPeople, m_dbConn);
            cmdCTP.ExecuteNonQuery();

            string ctShips = "CREATE TABLE ships (ShipName VARCHAR(20), Hull INT)";
            SQLiteCommand cmdCTS = new SQLiteCommand(ctShips, m_dbConn);
            cmdCTS.ExecuteNonQuery();

            string ctPorts = "CREATE TABLE ports (PortName VARCHAR(20), Population INT)";
            SQLiteCommand cmdCTPt = new SQLiteCommand(ctPorts, m_dbConn);
            cmdCTPt.ExecuteNonQuery();

            m_dbConn.Close();
}


Он вызывает исключение в строке 7 в cmdCTP.ExecuteNonQuery();

Это детали исключения:

System.Data.SQLite.SQLiteException was unhandled
  ErrorCode=1
  HResult=-2147467259
  Message=SQL logic error or missing database
table people already exists
  Source=System.Data.SQLite
  StackTrace:
       at System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn, String strSql, SQLiteStatement previous, UInt32 timeoutMS, String& strRemain)
       at System.Data.SQLite.SQLiteCommand.BuildNextCommand()
       at System.Data.SQLite.SQLiteCommand.GetStatement(Int32 index)
       at System.Data.SQLite.SQLiteDataReader.NextResult()
       at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
       at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
       at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery(CommandBehavior behavior)
       at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()
       at ShipsWPF.DatabaseTasks.CreateTables() in C:\Users\Keith\Documents\Visual Studio 2015\Projects\ShipsGame\WpfApplication2\DatabaseTasks.cs:line 67
       at ShipsWPF.Page1.button_Click(Object sender, RoutedEventArgs e) in C:\Users\Keith\Documents\Visual Studio 2015\Projects\ShipsGame\WpfApplication2\Page1.xaml.cs:line 36
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
       at System.Windows.Controls.Primitives.ButtonBase.OnClick()
       at System.Windows.Controls.Button.OnClick()
       at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e)
       at System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender, MouseButtonEventArgs e)
       at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
       at System.Windows.UIElement.OnMouseUpThunk(Object sender, MouseButtonEventArgs e)
       at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
       at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
       at System.Windows.Input.InputManager.ProcessStagingArea()
       at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
       at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
       at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
       at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
       at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
       at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
       at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
       at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
       at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
       at System.Windows.Application.RunDispatcher(Object ignore)
       at System.Windows.Application.RunInternal(Window window)
       at System.Windows.Application.Run(Window window)
       at System.Windows.Application.Run()
       at ShipsWPF.App.Main() in C:\Users\Keith\Documents\Visual Studio 2015\Projects\ShipsGame\WpfApplication2\obj\Debug\App.g.cs:line 0
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:


Что я уже пробовал:

Я не знаю, что попробовать, раньше это работало, а теперь нет, и как нуб у меня нет старой версии кода, чтобы сравнить ее. Я не менял CreateTables()

Главное, что я изменил, - это использование переменных класса для хранения dbPath и dbName, чтобы я мог использовать get/set.

Кроме того, будут оценены любые общие замечания о том, как я мог бы сделать код лучше.

1 Ответов

Рейтинг:
1

Maciej Los

Сообщение об ошибке совершенно ясно: table people already exists.
Прежде чем вы начнете создавать таблицы, вы должны проверить, существуют ли они уже.
1. кстати:

SELECT name FROM sqlite_master WHERE type='table' AND name='table_name';

2. кстати:
create table if not exists TableName (col1 typ1, ..., colN typN)

Другой способ-удалить таблицу перед созданием новой:
drop table if exists TableName


Источник: Как проверить в SQLite, существует ли таблица? - переполнение стека[^]


CPallini

5.

Keith Lewis

Я знаю, что это ошибка, но чего я не понимаю, так это почему он находит таблицу, когда должен заменить файл? Я вообще не хочу, чтобы он работал с существующим файлом, он должен создавать совершенно новую базу данных, прежде чем строить таблицы.

Maciej Los

Вы должны проверить, существует ли файл, тогда вы сможете удалить существующий файл и создать новую базу данных.

Keith Lewis

Однако savedialog уже проверяет это, он говорит: "этот файл уже существует, вы хотите его заменить?" Проблема в том, что он, очевидно, не заменяет его сейчас. Но я знаю, что он должен работать, потому что у меня он работал раньше, и я не знаю, что я изменил, что заставило его не работать. Я думаю, что должно быть что-то, что мешает файлу быть удаленным.

Maciej Los

Как я уже упоминал ранее, вы должны проверить, существует ли файл. Это означает, что метод SaveName не содержит:
if(IO.File.Exists(filename))
{
//delete file
}

Файл.Метод Exists (String)

Maciej Los

Спасибо, Карло.