2016-07-21 4 views
-1

У меня есть программа, которая имеет 11 переменных, которые необходимо вставить в базу данных SQL 2008 Express. Все работает до тех пор, пока переменные, которые могут быть NULL, являются NULL. Тогда SQL не получает данные. Вот мой код и оцените все, что может помочь:Как предотвратить предоставление нулевых значений в таблице

private void PostDatatoServer() 
     { 
      String connectionString = @"Data Source=LUCKYTIGER\SQLEXPRESS;Initial Catalog=John;Integrated Security=True"; 
      SqlConnection con = new SqlConnection(connectionString); 
      con.Open(); 
      textBox1.Text = "Connection made"; 
      SqlCommand cmd = con.CreateCommand(); 
      string str = ""; 
      str += "INSERT INTO Parsed(Date, Gal, Sys, Sl, ST, PN, PlayN, Sym, Rk, All, Rel)"; 
      str += "VALUES(@Date, @Gal, @Sys, @Sl, @ST, @PN, @PlayN, @Sym, @Rk, @All, @Rel)"; 
      SqlCommand cmd = new SqlCommand(str, con); 
      cmd.CommandType = CommandType.Text; 
      cmd.Parameters.Add(new SqlParameter("@Date", uegParser.strTime)); 
      cmd.Parameters.Add(new SqlParameter("@Gal", Convert.ToInt16(uegParser.strGalaxyNum))); 
      cmd.Parameters.Add(new SqlParameter("@Sys", Convert.ToInt16(uegParser.strSystemNum))); 
      cmd.Parameters.Add(new SqlParameter("@Sl", uegParser.intSlot)); 
      cmd.Parameters.Add(new SqlParameter("@ST", uegParser.intSlotType)); 
      if (uegParser.strPlanetName == "") 
       cmd.Parameters.Add(new SqlParameter("@PN", SqlDbType.NVarChar).Value = DBNull.Value); 
      else 
       cmd.Parameters.Add(new SqlParameter("@PN", uegParser.strPlanetName)); 
      if (uegParser.strPlayerName == "") 
      { 
       cmd.Parameters.Add(new SqlParameter("@PlayN", DBNull.Value)); 
       TextBox2.Text = "Null player name"; 
      } 
      else 
      { 
       cmd.Parameters.Add(new SqlParameter("@PlayN", uegParser.strPlayerName)); 
      } 
      if (uegParser.strSymbols == "") 
       cmd.Parameters.Add(new SqlParameter("@Sys", DBNull.Value)); 
      else 
       cmd.Parameters.Add(new SqlParameter("@Sym", uegParser.strSymbols)); 
      if (uegParser.strRank == "") 
       cmd.Parameters.Add(new SqlParameter("@Rk", DBNull.Value)); 
      else 
       cmd.Parameters.Add(new SqlParameter("@Rk", uegParser.strRank)); 
      if (uegParser.strAlliance == "") 
       cmd.Parameters.Add(new SqlParameter("@All", DBNull.Value)); 
      else 
       cmd.Parameters.Add(new SqlParameter("@All", uegParser.strAlliance)); 
      cmd.Parameters.Add(new SqlParameter("@Rel", uegParser.intRelationship)); 

      cmd.ExecuteNonQuery(); 
      con.Close(); 
      TextBox2.Text = "Connection closed"; 
     } 
+2

Что вы хотите сделать, если произошло нулевое значение? Запретить вставку? Вставить значение по умолчанию? – derpirscher

+1

Объявите столбцы как 'NOT NULL' или добавьте ограничение' NOT NULL'. –

+2

1 главное: использовать параметры для предотвращения sql-injection! .... –

ответ

1

Вы должны пересмотреть, как вы читаете свои данные из таблицы. Очевидно, вы положили весь лист в один большой DataTable, а затем перейдете к этому. Вы должны разделить свои данные, чтобы вы только прочитали первые два столбца в один DataTable и остальные пять столбцов на второй DataTable. Затем перейдите по двум DataTables отдельно и сохраните содержащиеся строки в базе данных.

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

if (!String.IsNullOrEmpty(Id) && !String.IsNullOrEmpty(Name)) { 
    cmd = new SqlCommand(....); 
    cmd.ExecuteNonQuery(); 
} 

Кроме того, некоторые намеки:

  1. Взгляните на параметризованных и подготовленных запросов, они делают код гораздо более безопасным.
  2. Вам не нужно открывать и закрывать ваше соединение sql для каждой отдельной команды. Вы можете открыть его перед циклом, создать и выполнить некоторые команды и закрыть его после цикла, когда вы закончите.
  3. Вам не хватает первой строки данных. Подавляющее большинство коллекций в C# начинаются с индекса 0.

EDIT

Для вашего запроса, я добавил нулевые чеки в код. Но я действительно не думаю, что вы должны сделать это так! Как я уже упоминал выше, вы должны разделить свой datatable на две таблицы, чтобы каждый из них содержал только соответствующие строки. И вы должны взглянуть на ответ Игоря о том, как создавать параметризованные запросы! И учтите другие намеки сверху. И, наконец, я не хочу быть грубым, но вы действительно должны взять хорошую книгу или несколько учебных пособий из Интернета и изучить основы, чтобы вы могли понять ответы на свой вопрос.

protected void btn_insert_Click(object sender, EventArgs e) 
    { 

     DataSet ds = new DataSet(); 
     ds = (DataSet)Session["DTset"]; 

     for (int i = 1; i < ds.Tables[0].Rows.Count; i++) 
     { 

      string Id = ds.Tables[0].Rows[i][0].ToString(); 
      string Name = ds.Tables[0].Rows[i][1].ToString(); 

      SqlConnection con = new SqlConnection(connStr); 
      SqlCommand cmd; 
      if (!string.IsNullOrEmpty(Id) && !string.IsNullOrEmpty(Name)) { 
       cmd = new SqlCommand("insert into tbl1(ID,Name) values ('" + Id + "','" + Name + "')", con); 
       con.Open(); 
       int j= cmd.ExecuteNonQuery(); 
       con.Close(); 
      } 

      string Id1 = ds.Tables[0].Rows[i][2].ToString(); 
      string Name1 = ds.Tables[0].Rows[i][3].ToString(); 
      string VehicleTypeId = ds.Tables[0].Rows[i][4].ToString(); 
      string VehicleType = ds.Tables[0].Rows[i][5].ToString(); 
      string Capacity = ds.Tables[0].Rows[i][6].ToString(); 


      if (!string.IsNullOrEmpty(Id1) && !string.IsNullOrEmpty(Name1) && !string.IsNullOrEmpty(VehicleTypeId) && !string.IsNullOrEmpty(VehicleType) && !string.IsNullOrEmpty(Capacity)) { 
       string InsQuery = "insert into tbl2(Id,Name,Subject,status,review) values ('" + Id1 + "','" + Name1 + "','" + Subject+ "','" + status+ "','" + review+ "')"; 
       cmd = new SqlCommand(InsQuery,con); 
       con.Open(); 
       int k= cmd.ExecuteNonQuery(); 
       con.Close(); 
      } 
     } 
    } 
+0

Вы можете увидеть, как создавать параметризованные запросы в ответе @ Igor – derpirscher

+0

Просто проверьте каждый параметр, который вы используете в первый запрос для null, тогда выполните первый запрос. Сделайте то же самое для значений для второго запроса, и если эти значения не равны нулю, выполните второй запрос, – derpirscher

2

Следующая не ответ на ваш вопрос но пример из всех мест, ваш код злоупотребляющих ADO.NET. Попробуйте перестроить любой код ado.net, который у вас есть таким образом. Я согласен с комментариями, ваш общий подход, вероятно, неверен, но это общие указатели, которые вы, возможно, извлечете выгоду из остальной части вашего кода. Указатели.

  • Всегда оберните SqlConnections при помощи блоков
  • Всегда использовать параметризованные запросы
    • Всегда указывайте параметр SqlDbType (при использовании SqlServer очевидно)
    • Всегда использовать правильные типы параметров вместо добавления строки значения

Реализованный адом.чистый код

protected void btn_insert_Click(object sender, EventArgs e) 
{ 
    DataSet ds = new DataSet(); 

    // i would not use Session unless necessary but that is out of scope for the question 
    // also do not forget to dispose the datatabale when finished and remove it from the session 
    ds = (DataSet)Session["DTset"]; 


    // always wrap your SqlConnection in a using block 
    // it ensures the connection is always released 
    // also there is no reason to have this inside the loop 
    // there is no reason to close/reopen it every time 
    using(SqlConnection con = new SqlConnection(connStr)) 
    { 
     con.Open(); // open once 
     for (int i = 1; i < ds.Tables[0].Rows.Count; i++) 
     { 
      // do not convert everything to strings, pick the correct type as it is in the table or convert it to the correct type if the table contains only strings 
      string Id = ds.Tables[0].Rows[i][0].ToString(); 
      string Name = ds.Tables[0].Rows[i][1].ToString(); 

      cmd = new SqlCommand("insert into tbl1(ID,Name) values (@ID,@Name)"; 
      cmd.Parameters.AddWithValue("@ID", Id).SqlDbType = SqlDbType.; // pick the correct dbtype 
      cmd.Parameters.AddWithValue("@Name", Name).SqlDbType = SqlDbType.; // pick the correct dbtype 
      int j= cmd.ExecuteNonQuery(); 

      // do not convert everything to strings, pick the correct type as it is in the table or convert it to the correct type if the table contains only strings 
      string Id1 = ds.Tables[0].Rows[i][2].ToString(); 
      string Name1 = ds.Tables[0].Rows[i][3].ToString(); 
      string VehicleTypeId = ds.Tables[0].Rows[i][4].ToString(); 
      string VehicleType = ds.Tables[0].Rows[i][5].ToString(); 
      string Capacity = ds.Tables[0].Rows[i][6].ToString(); 

      string InsQuery = "insert into tbl2(Id,Name,Subject,status,review) values (@Id,@Name,@Subject,@status,@review)"; 
      cmd = new SqlCommand(InsQuery,con); 
      cmd.Parameters.AddWithValue("@id", Id1).SqlDbType = SqlDbType.; // pick the correct dbtype 
      cmd.Parameters.AddWithValue("@Name", name1).SqlDbType = SqlDbType.; // pick the correct dbtype 
      // add the rest of your parameters here 

      int k= cmd.ExecuteNonQuery(); 
     } 
    } 
} 
+0

@ user6429940 - это тип данных для столбца, которому присваивается значение. Его перечисление, вам просто нужно заполнить его, используя правильное значение, например 'Int' или' BigInt' или 'Varchar' и т. Д. – Igor

+0

@ user6429940 - вот пример для' id', на основе этого я действительно надеюсь, что вы можете фигурировать остальные из них: 'cmd.Parameters.AddWithValue (« @ ID », Id) .SqlDbType = SqlDbType.Int;' (обратите внимание, что я добавил 'Int'). Список всех возможных значений перечисления см. В [SqlDbType] (https://msdn.microsoft.com/en-us/library/system.data.sqldbtype (v = vs.110) .aspx) – Igor

+0

@ user6429940 - вы посмотрите на перечисление? Длина varXXX (например, varchar) является другим свойством на 'SqlParameter' и не может быть установлена ​​с помощью' AddWithValue', но вам, вероятно, это не нужно. – Igor

0

Дурак доказательство решения: использование SQL хранимой процедуры.

--sql 
create procedure dbo.Parsed_i 
    @Date datetime, 
    @Gal int, 
    --so on 
    @PN nvarchar(100) = null --default value 
    --so on 
as 
INSERT INTO Parsed(Date, Gal, Sys, Sl, ST, PN, PlayN, Sym, Rk, All, Rel) 
VALUES(@Date, @Gal, @Sys, @Sl, @ST, @PN, @PlayN, @Sym, @Rk, @All, @Rel) 

//C# 
//... 
SqlCommand cmd = new SqlCommand("dbo.Parsed_i", con); 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.Parameters.Add("@ST", SqlDbType.Int).Value = uegParser.intSlotType; 
if (!string.IsNullOrEmpty(uegParser.strPlanetName)) 
    cmd.Parameters.Add("@PN", SqlDbType.NVarChar).Value = uegParser.strPlanetName; 
//note: no **else** part 
//so on 
Смежные вопросы