2017-01-27 10 views
1

У меня возникла проблема с проверкой двух значений в моей базе данных одновременно в одной строке, в моей таблице у меня есть 2 первичных ключа (Date и TagNumber), и перед тем, как я вставляю какие-либо новые данные, я хочу проверить наличие дубликатов записей.Как проверить дубликаты записей перед их вставкой в ​​DB (2 основных ключа)

Мне нужно проверить, что я не ввожу никаких новых данных с тем же date и тем же tagnumber.

Например: Current Record

Date: 25/03/2015 
TagNumber:111 

Когда новые данные мне нужно проверить, что Date и TagNumber не существуют на другой записи (как это было бы дубликат).

Так что, если новые данные

Date:25/03/2015 
TagNumber:111 

Эта запись будет уже существовать и пропускала вставки новой записи. Однако, если новые данные были:

Date:27/03/2015 
TagNumber:111 

Это будет новая запись и будет продолжать вставлять данные.

Код:

foreach (DataGridViewRow row in dataGridView1.Rows) 
     { 

      string constring = @"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\koni\Documents\Visual Studio 2015\Projects\t\Project\DB.mdf;Integrated Security=True"; 
      using (SqlConnection con = new SqlConnection(constring)) 
      { 

       using (SqlCommand sqlCommand = new SqlCommand("SELECT * from ResultsTable where [email protected] AND [email protected]", con)) 
       { 
        con.Open(); 
        string smdt1 = row.Cells["Exposure Date"].Value.ToString(); 
        string format1 = "dd.MM.yyyy"; 
        DateTime dt1 = DateTime.ParseExact(smdt1, format1, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); 

        sqlCommand.Parameters.AddWithValue("@Date", dt1); 
        sqlCommand.Parameters.AddWithValue("@TagNumber", row.Cells["Device #"].Value); 

       } 
      } 
     } 

и я попробовал уже ExecuteScalar() команду и не хороший - он работал только 1 параметр ....

ответ

0

Во-первых, его не совсем понятно, что содержится в этой таблице или ваших типах данных. Предположим, что ваши типы данных: TagNumber: int и Date: datetime.

Следующая Ваша проблема, вероятно, в поле даты.

DateTime dt1 = DateTime.ParseExact(smdt1, format1, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); 

Будет анализировать дату, как и следовало ожидать. Однако это также вернет время. Поэтому в вашем запросе параметр @Date также автоматически добавит временную часть к результату (поместите точку останова и посмотрите). Теперь, когда вы указали DateTimeStyles.AssumeUniversal, время установлено на 00:00:00 UTC, которое будет переведено в текущий часовой пояс. (Быть здесь, в Австралии, до 10:30:00).

sqlCommand.Parameters.AddWithValue("@Date", dt1.Date); //parsed date at midnight 00:00:00

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

Пример процедуры, такой как.

CREATE PROCEDURE InsertNewRecord 
    @TagNumber int, 
    @Date datetime 
AS 
BEGIN 
    SET NOCOUNT ON; 
    IF NOT EXISTS (SELECT TOP 1 1 FROM ResultsTable WHERE [Date] = @Date AND TagNumber = @TagNumber) 
     INSERT INTO ResultsTable (TagNumber, [Date]) VALUES (@TagNumber, @Date) 
END 
GO 

Дальше вы можете легко назвать это (обратите внимание, просто используя тестовые данные).

var tagNumber = "111"; 
var date = DateTime.ParseExact("28.01.2017", "dd.MM.yyyy", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); 

using(var con = new SqlConnection(connectionString)) 
{ 
    using(var cmd = new SqlCommand("EXEC InsertNewRecord @TagNumber, @Date", con)) 
    { 
     cmd.Parameters.AddWithValue("@TagNumber", tagNumber); 
     cmd.Parameters.AddWithValue("@Date", date.Date); 

     con.Open(); 
     cmd.ExecuteNonQuery(); 
     con.Close(); 
    } 

} 

Как видно из хранимой процедуры мы просто поиск информации первого (с помощью NOT EXISTS и выбор истинного результата ограничивающего к одной строке для выполнения SELECT TOP 1 1 FROM ... Возвращает одну строки 1, если оба числа тегов и дата существует на записи.

Теперь вы можете также изменить тип данных из datetime в date исключающего time части вашего @Date в параметре. Однако это потребует от вас, чтобы обеспечить ваши данные чисты и таблица должна быть восстановлена .

Один из последних вариантов заключается в том, чтобы направить поля datetime на date в ваш запрос и изменить параметр @Date на тип date, а затем проверить, равны ли они.

ALTER PROCEDURE InsertNewRecord 
    @TagNumber int, 
    @Date date 
AS 
BEGIN 
    SET NOCOUNT ON; 
    IF NOT EXISTS (SELECT TOP 1 1 FROM ResultsTable WHERE cast([Date] as date) = @Date AND TagNumber = @TagNumber) 
     INSERT INTO ResultsTable (TagNumber, [Date]) VALUES (@TagNumber, @Date) 
END 
GO 

Для Комплектности, если по каким-то причинам вы не хотите использовать хранимую процедуру следующий будет проверять, если запись существует (примечание, используя .Date свойство).

using (var con = new SqlConnection(connectionString)) 
{ 
    bool exists = false; 
    using(var cmd = new SqlCommand("SELECT TOP 1 1 FROM ResultsTable WHERE [email protected] AND [Date][email protected]", con)) 
    { 
     cmd.Parameters.AddWithValue("@TagNumber", tagNumber); 
     cmd.Parameters.AddWithValue("@Date", date.Date); 

     con.Open(); 
     var result = cmd.ExecuteScalar(); //returns object null if it doesnt exist 
     con.Close(); 

     exists = result != null; //result will be one or null. 
    } 
    if (exists) 
    { 
     //INSERT RECORD 
    } 
} 

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

0

Это должно быть сделано на стороне SQL. Передайте свои параметры в сохраненный процесс, который проверяет, существует ли запись в таблице, и если да, то либо возвращает ошибку, либо отбрасывает запись. Если он не существует, вставьте его в таблицу. Вы не можете сделать это на стороне клиента, так как у вас не будет полной таблицы в памяти.

0

Как пояснил @Nico, создание хранимой процедуры - лучший способ сделать это.