Andreea Samsanovici
Andreea Samsanovici

Reputation: 11

.NET framework SQL Server CRUD using data sets and data adapters

I have the following 2 tables in a database:

I wrote the following code but I still have to do the update/delete part and to add a new record in the child table

Code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace lab1_v2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            string connectionString = "Server=DESKTOP-T33VBF8;Database=lab1SGBD_v6;Integrated Security=true";

            try
            {
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    // Open connection
                    connection.Open();
                    MessageBox.Show("State of the connection: " + connection.State.ToString());

                    // Create the data set
                    DataSet dataset = new DataSet();
                    
                    // Create the two SQL Data Adapters for parent and child tables.
                    SqlDataAdapter parentAdapter = new SqlDataAdapter("SELECT * FROM Movies;", connection);
                    SqlDataAdapter childAdapter = new SqlDataAdapter("SELECT * FROM Languages;", connection);
                    
                    // Create and populate the parent DataTable and the child DataTable
                    parentAdapter.Fill(dataset, "Movies");
                    childAdapter.Fill(dataset, "Languages");
                    
                    // Create the two BindingSources for parent and child DataTable
                    BindingSource parentBS = new BindingSource();
                    BindingSource childBS = new BindingSource();
                    
                    // Show all the records from parent DataTable in dataGridViewParent
                    parentBS.DataSource = dataset.Tables["Movies"];
                    dataGridViewParent.DataSource = parentBS;
                   
                    // Create and add in the DataSet the DataRelation between parent DataTable and child DataTable
                    DataColumn parentPK = dataset.Tables["Movies"].Columns["id"];
                    DataColumn childFK = dataset.Tables["Languages"].Columns["movie_id"];
                    DataRelation relation = new DataRelation("fk_parent_child", parentPK, childFK);
                    dataset.Relations.Add(relation);
                    
                    // Show in dataGridView the child records which are from the parent record selected
                    childBS.DataSource = parentBS;
                    childBS.DataMember = "fk_parent_child";
                    dataGridViewChild.DataSource = childBS;
                }
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message.ToString());
            }
        }
    }
}

Upvotes: 0

Views: 551

Answers (1)

Caius Jard
Caius Jard

Reputation: 74605

You're making your life so difficult and complicated. Visual Studio can write literally every line youve written there, and more, in a couple of seconds.

  • start a new project (so you can throw it away if you don't like what I recommend, but you probably will)
  • add a new DataSet type of file to the project and open it
  • a blank grey surface appears, right click and choose Add TableAdapter
  • follow the wizard, enter your connection string, choose SQL statement, that downloads rows, type SELECT * FROM movies, name it, save it
  • add another table adapter in the same way but for languages (personally I don't think your relationship is correct, because a language has many movies and a movie has many languages so you should have both as parent tables and a MovieLanguage table to split them but hey.. let's go with your way for now)
  • if you have a relationship defined in the database then a line will appear already representing a DataRelation. If you don't have foreign key set up in your db then click one time on the faint grey left margin of the movie.id line in the table, so the whole line goes blue(not just the word), then click-hold in the same place (the margin) and start dragging over to languages.movie_id - a line follows as you drag so you're literally drawing the connection between the two columns. When you let go a window appears. Check that the columns are the right way round (parent is where you start the line, child is where you finish. If it's wrong either do the line again in the other direction or edit this dialog settings)
  • switch to forms designer
  • open the Data Sources tool panel (view menu, other windows)
  • drag the movies node out of the data sources and drop it onto the form
  • expand the movies node in the datasources and then drag the Languages node that is under it, out of the data sources window and onto the form
  • do not drag the Languages node that is the parent node out of the data sources window
  • check that your languagesbindingsource has a .DataSource of moviesbindingsource and a DataMember set to the name of the relation between the tables (you can see the relation name in the DataSet by right clicking and showing it or getting properties on it). If your languages binding source has a DataSource set to the name of the DataSet instead, you dragged the wrong languages node out of the datasources. Set the correct settings manually in the properties grid or Delete everything off the form and donit again making sure you drag the Languages that is a child of movies, out of data sources
  • run the program

Yes, that's it. There is no code for you to write. VS has written it all, literally everything in your question and more, including the insert, update and delete queries and they're all wired up- just press the save icon in the top right. Because the Languages bindingsource is bound to the movies bindingsource the grids work in a related fashion; whatever is the currently selected movie row forces a filter to only the languages relevant to that movie. Adding a new languages row relates it to the movie

Later when you want your app to be more useful than just "download the whole database into the DataSet" you can go back to the DataSet and right click the tableadapter and add another query, perhaps like SELECT * FROM movies WHERE title LIKE @title, call it FillByTitle and use it in code like moviesTableAdapter.FillByTitle(someDataSet.Movies, "Jaws%").

Remember that you have to fill all the related rows you want to use yourself too. For this reason I seldom make the first query in a tableadapter be a simple "select * from" - I always add a WHERE primarykeyid = @id then I can loop through movies filling each language id, or if performance is a concern I'll add another query to Languages like SELECT * FROM languages WHERE ID IN (SELECT DISTINCT languageid FROM movies WHERE title LIKE @title) so I can fill movies by Jaws% and then fill Languages by Jaws% too

Upvotes: 1

Related Questions