C # Question: Quelle est la façon la plus simple pour moi de charger un fichier .mdb, y apporter des modifications, et enregistrer les modifications dans le fichier d'origine?

StackOverflow https://stackoverflow.com/questions/518239

Question

Mon projet que je travaille est presque terminé. Je suis le chargement d'un fichier .mdb, afficher le contenu sur un DataGrid et tenter d'obtenir ces changements sur la grille de données et les enregistrer dans le fichier .mdb. Je vais aussi créer une fonction qui me permet de prendre les tables d'un fichier .mdb et enregistrez-le dans un autre fichier .mdb. Bien sûr, je ne peux pas faire tout cela si je ne peux pas comprendre comment enregistrer les modifications dans le fichier .mdb.

J'ai fait des recherches Google et abondamment il n'y a pas de réponse à ma question. Je me considère comme un débutant à ce sujet spécifique afin s'il vous plaît ne faites pas les réponses trop compliqué - je besoin de la façon la plus simple de modifier un fichier .mdb! S'il vous plaît fournir des exemples de programmation.

  1. On suppose que je l'ai déjà fait une connexion à un DataGrid. Comment puis-je obtenir les modifications apportées par le Datagrid? Je suis sûr que celui-ci est assez simple à répondre.
  2. J'ai besoin alors de savoir comment prendre cette Datatable, insérez-la dans Dataset il vient alors prendre ce Dataset et réécrire le fichier .mdb. (S'il y a un moyen de seulement insérer les tables qui ont été modifiées, je préférerais que.)

Je vous remercie à l'avance, laissez-moi savoir si vous avez besoin de plus amples informations. C'est la dernière chose que je vais probablement devoir poser des questions sur ce sujet ... Dieu merci.

EDIT:

Le .mdb Je travaille avec est un (je ne ai pas même sais qu'il y avait plusieurs fichiers .mdb) Base de données Microsoft Access.

Je sais que je ne peux pas écrire directement au fichier .mdb via un StreamWriter ou quoi que ce soit, mais est-il un moyen que je peux peut-être généré un fichier .mdb avec les informations DataSet déjà en elle? Ou est-il juste une façon que je peux ajouter des tables à un fichier .mdb que je l'ai déjà chargé dans le DataGrid. Il doit y avoir un moyen!

Encore une fois, je besoin d'un moyen de le faire Programmatically en C #.

EDIT:

D'accord, mon projet est assez important mais j'utiliser un fichier séparé de classe pour gérer toutes les connexions de base de données. Je sais que ma conception et la source est vraiment bâclée, mais il fait le travail. Je suis aussi bon que les exemples que je trouve sur Internet.

Rappelez-vous, je suis tout simplement se connecter à une DataGrid sous une autre forme. Faites-moi savoir si vous voulez mon code de la forme Datagrid (je ne sais pas pourquoi vous besoin bien). 2 poignées DatabaseHandling.cs fichiers .mdb. Vous verrez donc deux ensembles de données là-dedans. Je vais utiliser ce terme pour prendre les tables d'un DataSet et les mettre dans une autre Dataset. J'ai juste besoin de savoir comment sauvegarder ces valeurs dans un fichier DOS .mdb.

Y at-il de toute façon de le faire? Il doit y avoir une façon ...

EDIT:

D'après ce que j'ai lu et fait des recherches ... Je pense que la réponse est juste sous mon nez. En utilisant la commande "Update ()". Maintenant, alors que cela est ré-assurer qu'il est enfait un moyen simple de faire cela, je suis toujours parti avec le problème que je n'ai pas la moindre idée-friggin-comment utiliser cette commande de mise à jour.

Peut-être que je peux le configurer comme ceci:

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)"; 

Je pense que peut le faire, mais je ne veux pas insérer manuellement quoi que ce soit. Je veux faire ces deux au lieu:

  • Prendre des informations est modifiée sur la que je l'ai obtenu de Datagrid et mettre à jour le fichier de base de données Access (.mdb)
  • Créer une fonction qui me permet de prendre des tables d'un autre fichier base de données Access (.mdb) et de les remplacer dans un fichier de base de données d'accès secondaire (.mdb). Les deux fichiers utilisent exactement la même structure, mais ils ont des informations différentes.

J'espère que quelqu'un arrive avec une réponse pour cela ... mon projet est fait tout ce qui vous attend est une réponse simple.

Merci encore à l'avance.

EDIT:

D'accord ... bonnes nouvelles. Je l'ai compris comment interroger le fichier .mdb lui-même (je pense). Voici le code, ce qui ne fonctionne pas parce que je reçois une erreur d'exécution en raison de la commande SQL que je tente d'utiliser. Ce qui me mènera à ma question suivante.

Nouveau code de fonction ajoutée à 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();
}

Comme vous pouvez le voir, je l'ai effectivement réussi à exécuter une requête sur la connexion elle-même, que je crois être l'accès fichier .mdb réel. Comme je l'ai dit cependant, la requête SQL que j'ai exécuté sur le fichier ne fonctionne pas et a généré une erreur d'exécution quand il est utilisé.

La commande je tente d'exécuter est censé prendre une table à partir d'un fichier .mdb et remplacer une table du même type d'un fichier .mdb différent. La commande SQL ci-dessus je tentais essayé de prendre directement une table à partir d'un fichier .mdb et mis directement dans un autre - ce n'est pas ce que je veux faire. Je veux profiter de toutes les informations du fichier .mdb - (. Que je l'ai fait) mettre les tables en Datatable puis ajouter tous les datatables à un DataSet que je veux faire cela pour deux fichiers .mdb. Une fois que j'ai deux datasets je veux prendre des tables spécifiques de chaque Dataset et les ajouter à chaque fichier comme ceci:

  • DataSetA >>>> ----- [Ajouter des tables (Ecraser eux)] ----- >>>> DataSetB
  • DataSetB >>>> ----- [Ajouter des tables (Ecraser eux)] ----- >>>> DataSetA

Je veux prendre les chacun de ces jeux de données, puis les remettre dans chaque fichier .mdb accès ils venaient. Essentiellement en gardant les deux bases de données synchronisées.

Alors mes questions, révisées, est:

  1. Comment puis-je créer une requête SQL qui va ajouter une table au fichier .mdb en réécrivant l'existant du même nom. La requête doit pouvoir être créé dynamiquement lors de l'exécution d'un tableau qui remplace une variable avec le nom de la table que je veux ajouter.
  2. Comment puis-je obtenir les modifications apportées par le Datagrid au DataTable et les remettre dans un DataTable (ou DataSet) afin que je puisse les envoyer au .mdb?

J'ai essayé d'élaborer autant que possible ... parce que je crois que je ne suis pas explaing ma question très bien. Maintenant, cette question est devenue wayyy trop longtemps. Je souhaite juste que je pourrais expliquer mieux. : [

EDIT:

Merci à un internaute ci-dessous, je pense que je l'ai presque trouvé une solution - le mot-clé presque . Voici mon code DatabaseHandling.cs mis à jour ci-dessous. Je reçois une erreur d'exécution « Datatype Mismatch. » Je ne sais pas comment cela pourrait être possible étant donné que je suis en train de copier ces tables dans une autre base de données avec la même configuration exacte.

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();
                }
            }

            }          
        }

Pourquoi suis-je recevoir cette erreur? Les deux tables sont exactement les mêmes. Qu'est-ce que je fais mal? Le pire des cas, comment puis-je supprimer la table dans l'autre fichier Access .MDB avant d'insérer la même table de structure exacte avec des valeurs différentes en elle?

L'homme que je souhaite que je pouvais comprendre cela ...

EDIT:

D'accord, je suis venu à une certaine distance. Ma question est transformée en une nouvelle, et mérite donc d'être posée séparément. J'ai eu réponse à ma question que je sais maintenant comment exécuter des requêtes directement à la connexion que j'ai ouvert. Merci à tous!

Était-ce utile?

La solution

Je ne sais pas à quel point vous avez obtenu, mais si vous cherchez une opération de glisser-déposer rapidement vous pouvez envisager la création d'un ensemble de données fortement typé qui se connecte, et en utilisant les fonctions glisser-déposer de la DataSources fenêtre d'outils dans Visual studio.

Il y a des échantillons certainement là-bas, mais vous voulez.

  1. Créer un nouveau DataSet
  2. Faites glisser-déposer de votre arbre DataConnection dans l'Explorateur de serveurs
  3. Créer un nouveau formulaire
  4. Faites glisser la table à partir de l'outil DataSources
  5. Fenêtre sur le formulaire.
  6. le tour est joué

Mise à jour:

Tout d'abord, je ne suis pas à 100% que je comprends votre question. Si vous pouvez créer des LinkTables entre les fichiers d'accès qui serait le mieux, alors vous pouvez copier les données entre les fichiers en utilisant une instruction SQL comme 'INSERT INTO SELECT Customers FirstName, LastName DE File2.Customers. Si c'est pas et l'option Je pense que vous allez avoir à boucler les DataTables et insérer les enregistrements manuellement à l'aide instructions INSERT similaires à la dernière édition. Quant à la grille de données, vous aurez probablement de garder une trace de ce qui est changé en surveillant l'événement RowChanged (pas sûr si c'est l'événement exact) de faire même les instructions d'insertion / mise à jour lorsque les changements de ligne.

Mise à jour:

pour boucler la datatable vous ferait quelque chose comme ça. pas testé. Je viens de nouveau mis à jour pour inclure cette fonction MakeValueDbReady. Ce n'est pas testé non plus et je ne sais pas si j'ai traiter tous les cas, ou même tous les cas correctement. Vous aurez vraiment déboguer l'instruction SQL et assurez-vous de sa génération la bonne valeur. Chaque base de données gère des valeurs est différente. Atleast cette façon, l'analyse syntaxique de la valeur est extraite loin. J'ai aussi réalisé qu'au lieu de coder en dur l'TableName vous devriez être en mesure d'obtenir d'une propriété sur le 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();
    }
}

Autres conseils

Pour mettre à jour le fichier MDB d'origine avec les modifications apportées à DataSet (pas le DataGrid, puisque c'est juste l'interface utilisateur sur le DataSet) il suffit d'utiliser le la commande de DataAdapter.Update.

Pour déplacer les tables de 1 à l'autre est un peu plus délicat. Si la table n'existe pas déjà dans la destination, vous devrez créer à l'aide d'un SQL CREATE . Puis, DataAdapter.Fill un DataSet de la source . Boucle à travers chaque ligne et réglez son état de RowAdded en appelant DataRow.SetAdded . Ensuite, renvoient la balle à un DataAdapter.Update du destination base de données.

EDIT: code se trouve sur la question suivante ....

Il y a en fait plus d'un format de fichier avec l'extension .mdb. Donc, si je pense que le mauvais, ce sera la mauvaise réponse. Mais, cela ressemble à un problème de Microsoft Access.

Vous n'écrivez pas directement à un fichier MDB. Ils sont cryptés et compressés. La meilleure façon de modifier un fichier MDB est de le charger par Access et copier les tables par les méthodes fournies.

Comment vous connectez à la base de données (le fichier .mdb)? Pourriez-vous poster quelques exemples de code? Si vous vous connectez correctement que toutes les opérations SQL que vous exécutez contre il doit être enregistré dans la base de données automatiquement.

Une fois que vous connectez à la base de données, vous pouvez exécuter SQL qui va créer des tables, insérer / mettre à jour / récupérer des données, etc. Essayer de construire un fichier .mdb à la main n'est pas conseillé.

Voici un exemple:

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top