2009-02-05 1 views
5

Мой проект, над которым я работаю, почти закончен. Я загружаю файл .MDB, отображая содержимое в DataGrid и пытаясь получить эти изменения в DataGrid и сохраняя их обратно в файл .MDB. Я также собираюсь создать функцию, которая позволяет мне принимать таблицы из одного файла .MDB и сохранять его в другом .MDB-файле. Конечно, я не могу ничего сделать, если не могу понять, как сохранить изменения обратно в файл .MDB.Проблема с C#: Какой самый простой способ загрузить файл .MDB, внести в него изменения и сохранить изменения в исходный файл?

Я внимательно изучил Google, и на мой вопрос нет ответов. Я считаю себя новичком в этой конкретной теме, поэтому, пожалуйста, не делайте ответы слишком сложными - мне нужен самый простой способ редактировать файл .MDB! Просьба представить примеры программирования.

  1. Предположим, что я уже подключился к DataGrid. Как получить изменения, внесенные Datagrid? Я уверен, что это достаточно просто, чтобы ответить.
  2. Мне тогда нужно знать, как взять этот Datatable, вставить его в набор данных, откуда он пришел, затем взять этот набор данных и переписать файл .MDB. (Если есть способ только вставить таблицы, которые были изменены, я бы предпочел это.)

Спасибо заранее, дайте мне знать, если вам нужна дополнительная информация. Это последнее, что мне, вероятно, придется спросить об этой теме ... слава богу.

EDIT:

.mdb Я работаю с базой данных является Microsoft Access. (я даже не знал, что было несколько файлов .mdb)

Я знаю, что не могу писать непосредственно в файл .MDB через потоковик или что-то еще, но есть способ, которым я могу сгенерировать файл .MDB с информацией DataSet уже в нем? ИЛИ есть только способ, которым я могу добавить таблицы в файл .MDB, который уже загружен в DataGrid. Там должен быть путь!

Опять же, мне нужен способ, чтобы сделать это в C# Программным способом.

EDIT:

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

Помните, что я просто подключаюсь к DataGrid в другой форме. Дайте мне знать, если вы хотите, чтобы мой код из формы Datagrid (я не знаю, зачем вам это нужно). DatabaseHandling.cs обрабатывает файлы 2.MDB. Таким образом, вы увидите два набора данных. Я буду использовать это в конечном счете, чтобы взять таблицы из одного набора Данных и поместить их в другой Набор данных. Мне просто нужно выяснить, как сохранить эти значения BACK в .MDB-файле.

Есть ли все равно для этого? Там должен быть путь ...

EDIT:

Из того, что я исследовал и читать ... Я думаю, что ответ находится прямо у меня под носом. Использование команды «Обновить()».Теперь, когда это подтверждается тем, что на самом деле существует простой способ сделать это, мне все еще остается проблема, связанная с тем, что я не знаю, как использовать эту команду обновления.

Возможно, я могу настроить его так:

Oledb.OledbConnection cn = new Oledb.OledbConnection(); 
cn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Staff.mdb"; 
Oledb.OledbCommand cmd = new Oledb.OledbCommand(cn); 
cmd.CommandText = "INSERT INTO Customers (FirstName, LastName) VALUES (@FirstName, @LastName)"; 

Я думаю, что может это сделать, но я не хочу, чтобы вручную вставить что-нибудь. Я хочу, чтобы сделать оба из них вместо того, чтобы:

  • Возьмите информацию, которая меняется на Datagrid и обновление базы данных Access File (MDB), который я получил его от
  • Создайте функцию, которая позволяет мне брать таблицы из другого файла базы данных доступа (.mdb) и замените их в дополнительном файле базы данных Access (.mdb). Оба файла будут использовать ту же структуру, но будут иметь в них различную информацию.

Надеюсь, что кто-то придумает ответ на этот вопрос ... мой проект сделан всем, что ждет, это один простой ответ.

Еще раз заблаговременно.

EDIT:

Хорошо ... хорошие новости. Я выяснил, как запросить сам файл .mdb (я думаю). Вот код, который не работает, потому что я получаю ошибку времени выполнения из-за команды sql, которую я пытаюсь использовать. Это приведет меня к следующему вопросу.

Новый код функции добавлены в DatabaseHandling.cs:

static public void performSynchronization(string table, string tableTwoLocation) 
{ 
    OleDbCommand cmdCopyTables = new OleDbCommand("INSERT INTO" + table + "SELECT * FROM [MS Access;" + tableTwoLocation + ";].[" + table + "]"); // This query generates runtime error 
    cmdCopyTables.Connection = dataconnectionA; 
    dataconnectionA.Open(); 
    cmdCopyTables.ExecuteNonQuery(); 
    dataconnectionA.Close(); 
} 

Как вы можете видеть, я на самом деле удалось выполнить запрос на само соединение, которое я считаю, что фактический доступ. MDB-файл. Как я уже сказал, SQL-запрос, который я выполнил в файле, не работает и генерировал ошибку во время выполнения.

Команда, которую я пытаюсь выполнить, должна взять таблицу из файла .MDB и перезаписать таблицу того же типа другого .MDB-файла. Команда SQL, с которой я попыталась выше, попыталась напрямую взять таблицу из файла .mdb и напрямую поместить ее в другую - это не то, что я хочу сделать. Я хочу взять всю информацию из файла .MDB - поместить таблицы в Datatable, а затем добавить все Datatables в набор данных (который я сделал.) Я хочу сделать это для двух файлов .MDB. После того, как у меня есть два набора данных, я хочу, чтобы принять конкретные таблицы из каждого набора данных и добавить их к каждому файлу, как это:

  • DataSetA >>>> ----- [Добавить таблицы (перезаписывать)] - ---- >>>> DataSetB
  • DataSetB >>>> ----- [Добавить Таблицы (перезаписывать)] ----- >>>> DataSetA

Я хочу возьмите те из этих наборов данных, а затем поместите их НАЗАД в каждый файл Access .MDB, из которого они пришли. По существу, синхронизация обеих баз данных.

Так что мои вопросы, переработанное, является:

  1. Как создать SQL запрос, который будет добавить таблицу в файл .MDB путем перезаписи существующего одного и того же имени.Запрос должен быть динамически создан во время выполнения с массивом, который заменяет переменную именем таблицы, которую я хочу добавить.
  2. Как получить изменения, внесенные Datagrid в DataTable, и поместить их обратно в DataTable (или DataSet), чтобы я мог отправить их в файл .MDB?

Я старался как можно подробнее уточнить ... потому что я считаю, что я не очень хорошо объясняю свою проблему. Теперь этот вопрос слишком долго расти. Я просто хочу, чтобы я мог объяснить это лучше. : [

EDIT:

Благодаря пользователю ниже я думаю, что я почти нашел исправление - ключевое слово почти. Вот мой обновленный код DatabaseHandling.cs ниже. Я получаю ошибку времени выполнения "Datatype Mismatch." Я не знаю, как это возможно, учитывая, что я пытаюсь скопировать эти таблицы в другую базу данных с той же самой настройкой.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data.OleDb; 
using System.Data; 
using System.IO; 

    namespace LCR_ShepherdStaffupdater_1._0 
    { 
     public class DatabaseHandling 
     { 
      static DataTable datatableB = new DataTable(); 
      static DataTable datatableA = new DataTable(); 
      public static DataSet datasetA = new DataSet(); 
      public static DataSet datasetB = new DataSet(); 
      static OleDbDataAdapter adapterA = new OleDbDataAdapter(); 
      static OleDbDataAdapter adapterB = new OleDbDataAdapter(); 
      static string connectionstringA = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + Settings.getfilelocationA(); 
      static string connectionstringB = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + Settings.getfilelocationB(); 
      static OleDbConnection dataconnectionB = new OleDbConnection(connectionstringB); 
      static OleDbConnection dataconnectionA = new OleDbConnection(connectionstringA); 
      static DataTable tableListA; 
      static DataTable tableListB; 

      static public void addTableA(string table, bool addtoDataSet) 
      { 
       dataconnectionA.Open(); 
       datatableA = new DataTable(table); 
       try 
       { 
        OleDbCommand commandselectA = new OleDbCommand("SELECT * FROM [" + table + "]", dataconnectionA); 
        adapterA.SelectCommand = commandselectA; 
        adapterA.Fill(datatableA); 
       } 
       catch 
       { 
        Logging.updateLog("Error: Tried to get " + table + " from DataSetA. Table doesn't exist!"); 
       } 

       if (addtoDataSet == true) 
       { 
        datasetA.Tables.Add(datatableA); 
        Logging.updateLog("Added DataTableA: " + datatableA.TableName.ToString() + " Successfully!"); 
       } 

       dataconnectionA.Close(); 
      } 

      static public void addTableB(string table, bool addtoDataSet) 
      { 
       dataconnectionB.Open(); 
       datatableB = new DataTable(table); 

       try 
       { 
        OleDbCommand commandselectB = new OleDbCommand("SELECT * FROM [" + table + "]", dataconnectionB); 
        adapterB.SelectCommand = commandselectB; 
        adapterB.Fill(datatableB); 
       } 
       catch 
       { 
        Logging.updateLog("Error: Tried to get " + table + " from DataSetB. Table doesn't exist!"); 
       } 



       if (addtoDataSet == true) 
       { 
        datasetB.Tables.Add(datatableB); 
        Logging.updateLog("Added DataTableB: " + datatableB.TableName.ToString() + " Successfully!"); 
       } 

       dataconnectionB.Close(); 
      } 

      static public string[] getTablesA(string connectionString) 
      { 
       dataconnectionA.Open(); 
       tableListA = dataconnectionA.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" }); 
       string[] stringTableListA = new string[tableListA.Rows.Count]; 

       for (int i = 0; i < tableListA.Rows.Count; i++) 
       { 
        stringTableListA[i] = tableListA.Rows[i].ItemArray[2].ToString(); 
       } 
       dataconnectionA.Close(); 
       return stringTableListA; 
      } 

      static public string[] getTablesB(string connectionString) 
      { 
       dataconnectionB.Open(); 
       tableListB = dataconnectionB.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" }); 
       string[] stringTableListB = new string[tableListB.Rows.Count]; 

       for (int i = 0; i < tableListB.Rows.Count; i++) 
       { 
        stringTableListB[i] = tableListB.Rows[i].ItemArray[2].ToString(); 
       } 
       dataconnectionB.Close(); 
       return stringTableListB; 
      } 

      static public void createDataSet() 
      { 

       string[] tempA = getTablesA(connectionstringA); 
       string[] tempB = getTablesB(connectionstringB); 
       int percentage = 0; 
       int maximum = (tempA.Length + tempB.Length); 

       Logging.updateNotice("Loading Tables..."); 
       for (int i = 0; i < tempA.Length ; i++) 
       { 
        if (!datasetA.Tables.Contains(tempA[i])) 
        { 
         addTableA(tempA[i], true); 
         percentage++; 
         Logging.loadStatus(percentage, maximum); 
        } 
        else 
        { 
         datasetA.Tables.Remove(tempA[i]); 
         addTableA(tempA[i], true); 
         percentage++; 
         Logging.loadStatus(percentage, maximum); 
        } 
       } 

       for (int i = 0; i < tempB.Length ; i++) 
       { 
        if (!datasetB.Tables.Contains(tempB[i])) 
        { 
         addTableB(tempB[i], true); 
         percentage++; 
         Logging.loadStatus(percentage, maximum); 
        } 
        else 
        { 
         datasetB.Tables.Remove(tempB[i]); 
         addTableB(tempB[i], true); 
         percentage++; 
         Logging.loadStatus(percentage, maximum); 
        } 
       } 


      } 

      static public DataTable getDataTableA() 
      { 
       datatableA = datasetA.Tables[Settings.textA]; 

       return datatableA; 
      } 
      static public DataTable getDataTableB() 
      { 
       datatableB = datasetB.Tables[Settings.textB]; 
       return datatableB; 
      } 

      static public DataSet getDataSetA() 
      { 
       return datasetA; 
      } 

      static public DataSet getDataSetB() 
      { 
       return datasetB; 
      } 

      static public void InitiateCopyProcessA() 
      { 
       DataSet tablesA; 
       tablesA = DatabaseHandling.getDataSetA(); 

       foreach (DataTable table in tablesA.Tables) 
       { 
        CopyTable(table, connectionstringB); 
       } 
      } 

      public static void CopyTable(DataTable table, string connectionStringB) 
      { 
       var connectionB = new OleDbConnection(connectionStringB); 
       foreach (DataRow row in table.Rows) 
       { 
        InsertRow(row, table.Columns, table.TableName, connectionB); 
       } 
      } 

      public static void InsertRow(DataRow row, DataColumnCollection columns, string table, OleDbConnection connection) 
      { 
       var columnNames = new List<string>(); 
       var values = new List<string>(); 

       for (int i = 0; i < columns.Count; i++) 
       { 
        columnNames.Add("[" + columns[i].ColumnName + "]"); 
        values.Add("'" + row[i].ToString().Replace("'", "''") + "'"); 
       } 

       string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", 
         table, 
         string.Join(", ", columnNames.ToArray()), 
         string.Join(", ", values.ToArray()) 
        ); 

       ExecuteNonQuery(sql, connection); 
      } 

      public static void ExecuteNonQuery(string sql, OleDbConnection conn) 
      { 
       if (conn == null) 
        throw new ArgumentNullException("conn"); 

       ConnectionState prevState = ConnectionState.Closed; 
       var command = new OleDbCommand(sql, conn); 
       try 
       { 
        prevState = conn.State; 
        if (prevState != ConnectionState.Open) 
         conn.Open(); 

        command.ExecuteNonQuery(); // !!! Runtime-Error: Data type mismatch in criteria expression. !!! 
       } 
       finally 
       { 
        if (conn.State != ConnectionState.Closed 
         && prevState != ConnectionState.Open) 
         conn.Close(); 
       } 
      } 

      }   
     } 

Почему я получаю эту ошибку? Обе таблицы одинаковы. Что я делаю не так? Худший случай, как мне удалить таблицу в другом файле Access .MDB, прежде чем вставлять в нее ту же самую таблицу структуры с разными значениями?

Man Я хотел бы просто понять это ...

EDIT:

Хорошо, я пришел на некоторое расстояние. Мой вопрос превратился в новый, и поэтому заслуживает того, чтобы его спросили отдельно. На мой вопрос был ответ, так как теперь я знаю, как выполнять запросы непосредственно к открытому мне соединению. Спасибо вам всем!

+0

@Remou: пытается привлечь ваше внимание здесь - вы делаете плохую ситуацию хуже. Доступ! = MDB. Все эти вопросы, которые вы перемаркируете с MDB на MS-ACCESS, не связаны с доступом вообще, а только с механизмом базы данных Jet/ACE. Я перемаркирован соответствующим образом. –

+0

@Remou @David W. Fenton: Я поднял эту проблему на мета: http://meta.stackoverflow.com/questions/33216/ms-access-or-mdb-or-access-database-engine-or- ms-jet-ace – onedaywhen

+0

Я уже размещен на Meta. MDB также равен Message-Driven Beans, поэтому он является двусмысленным тегом и, подобно Access, который помечен как ms-access из-за неоднозначности, нуждается в изменении. – Fionnuala

ответ

3

Я не уверен, насколько вы получили, но если вы ищете быструю операцию перетаскивания, вам может потребоваться создать сильно типизированный набор данных, который соединяется, и используя функции перетаскивания Окно инструментов DataSources в Visual Studio.

Есть определенные образцы там, но вы захотите.

  1. Создать новый DataSet
  2. Drag-н-Drop из вашего DataConnection Дерево в Server Explorer
  3. Создать новую форму
  4. Перетащите таблицу с помощью инструмента DataSources
  5. Окно в форме ,
  6. вуаля

Update:

Во-первых, я не 100%, что я понимаю ваш вопрос. Если вы можете создать некоторые ссылочные таблицы между файлами доступа, которые были бы лучше всего, то вы можете скопировать данные между файлами с помощью оператора sql, такого как «INSERT INTO Customers SELECT FirstName, LastName FROM File2.Customers». Если это не так и вариант, я думаю, что вам нужно будет зацикливать DataTables и вставить записи вручную, используя инструкции INSERT, похожие на ваши последние изменения. Что касается datagrid, вам, вероятно, придется отслеживать, что изменилось, отслеживая событие RowChanged (не уверен, что это точное событие) даже делает инструкции insert/update при изменении строки.

Update:

для автоматического повтора DataTable вы могли бы сделать что-то вроде этого. не испытано. Я просто обновил это снова, включив функцию MakeValueDbReady. Это тоже не проверено, и я не уверен, правильно ли обработал все случаи или даже все случаи. Вам действительно придется отлаживать инструкцию sql и убедиться, что она генерирует правильное значение. Каждая запись базы данных имеет значения по-разному. По крайней мере таким образом вычисляется значение. Я также понял, что вместо жесткого кодирования TableName вы должны быть в состоянии получить его от собственности на DataTable

void CopyTable(DataTable table, string connectionStringB) 
{ 
    var connectionB = new OleDbConnection(connectionStringB); 
    foreach(DataRow row in table.Rows) 
    { 
     InsertRow(row, table.Columns, table.TableName, connectionB); 
    } 
} 

public static void InsertRow(DataRow row, DataColumnCollection columns, string table, OleDbConnection connection) 
{ 
    var columnNames = new List<string>(); 
    var values = new List<string>(); 

    // generate the column and value names from the datacolumns  
    for(int i =0;i<columns.Count; i++) 
    { 
     columnNames.Add("[" + columns[i].ColumnName + "]"); 
     // datatype mismatch should be fixed by this function 
     values.Add(MakeValueDbReady(row[i], columns[i].DataType)); 
    } 

    // create the sql 
    string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", 
      table, 
      string.Join(", ", columnNames.ToArray()), 
      string.Join(", ", values.ToArray()) 
     ); 

    // debug the accuracy of the sql here and even copy into 
    // a new Query in Access to test 
    ExecuteNonQuery(sql, connection); 
} 

// as the name says we are going to check the datatype and format the value 
// in the sql string based on the type that the database is expecting 
public string MakeValueDbReady(object value, Type dataType) 
{ 
    if (value == null) 
     return null; 

    if (dataType == typeof(string)) 
    { 
     return "'" + value.ToString().Replace("'", "''") + "'" 
    } 
    else if (dataType == typeof(DateTime)) 
    { 
     return "#" + ((DateTime)value).ToString + "#" 
    } 
    else if (dataType == typeof(bool)) 
    { 
     return ((bool)value) ? "1" : "0"; 
    } 

    return value.ToString(); 
} 

public static void ExecuteNonQuery(string sql, OleDbConnection conn) 
{ 
    if (conn == null) 
     throw new ArgumentNullException("conn"); 

    ConnectionState prevState = ConnectionState.Closed; 
    var command = new OleDbCommand(sql, conn); 
    try 
    { 
     // the reason we are checking the prev state is for performance reasons 
     // later you might want to open the connection once for the a batch 
     // of say 500 rows or even wrap your connection in a transaction. 
     // we don't want to open and close 500 connections 
     prevState = conn.State; 
     if (prevState != ConnectionState.Open) 
      conn.Open(); 

     command.ExecuteNonQuery(); 
    } 
    finally 
    { 
     if (conn.State != ConnectionState.Closed 
      && prevState != ConnectionState.Open) 
      conn.Close(); 
    } 
} 
+0

Я получил очень далеко от своего проекта. У меня уже есть все функции, запрограммированные для получения файла .MDB, отображения информации и изменения информации. Мой пользовательский интерфейс уже завершен, мне просто нужен способ вернуть эту информацию в файл .MDB (или, желательно, тот же самый .MDB, из которого он пришел) – OneShot

+0

И вызывать инструкции UPDATE не будут работать для вас? – bendewey

+0

Я уверен, что так и будет. Что я могу назвать оператором обновления TO. Я называю это в соединении, которое я сделал в файле ??? – OneShot

0

На самом деле существует более одного формата файла с расширением .mdb. Итак, если я ошибаюсь, это будет неправильный ответ. Но это похоже на проблему с Microsoft Access.

Вы не пишете непосредственно в файл MDB. Они шифруются и сжимаются. Самый простой способ изменить файл MDB - загрузить его через Access и скопировать таблицы с помощью предоставленных методов.

+0

Да Я использую формат Microsoft Access для файла .mdb. Я знаю, что не пишу непосредственно в файл MDB.Мне нужен способ вставить новые таблицы или создать файл .MDB с уже имеющейся информацией (например, набор данных, полный таблиц). – OneShot

0

Как вы подключения к базе данных (файл .mdb)? Не могли бы вы разместить несколько примеров кода? Если вы подключаетесь к нему правильно, чем любые выполняемые вами SQL-операции, они должны автоматически сохраняться в базе данных.

Итак, после подключения к базе данных вы можете выполнить SQL, который будет создавать таблицы, вставлять/обновлять/извлекать данные и т. Д. Попытка создания файла .mdb вручную не рекомендуется.

Вот пример:

http://www.java2s.com/Code/CSharp/Database-ADO.net/Access.htm

+0

См. Мой код. Итак, вы говорите, если я выполняю команду SQL, которая удаляет что-то, что будет отображаться в моем файле .Mdb? Возможно, у меня уже есть это, где все, что я делаю, сохраняется в файле. Я не знаю, что я делаю. Как я могу сохранить изменения из Datagrid в .MDB-файле? – OneShot

1

Чтобы обновить исходное MDB файл с изменениями, внесенными в наборе данных (не DataGrid, так как это только интерфейс через DataSet) используйте команду DataAdapter.Update.

Перемещение таблиц от 1 к другому немного сложнее. Если таблица не существует в месте назначения, вам необходимо создать ее, используя SQL CREATE statement. Затем DataAdapter.Fill a DataSet от источника . Прокрутите каждую строку и установите ее состояние в RowAdded, вызвав DataRow.SetAdded. Затем передайте его обратно в DataAdapter.Update из базы данных .

EDIT: Code is on the next question....

+0

Отлично! Если вы можете просто показать мне какой-то код, чтобы я мог привести пример ... Я думаю, что он это сделает. Мне все еще нужно выяснить, как добавить изменения, внесенные DataGrid. Вы сказали DataRow.SetAdded. Почему я должен добавлять строки, когда мне нужно добавлять целые таблицы? Каждая перемещаемая таблица уже существует. 100% перезаписать – OneShot

Смежные вопросы