2011-11-16 12 views
9

Biorę dane, które znajduje się w List z Record obiektów i umieszczenie ich zawartość do bazy danych:C# SqlParameters Krótki Ręcznie

// Processes a Record and adds it to the database 
public bool addRecord(SqlConnection db, List<Record> recordsToAdd) 
{ 
    using (SqlCommand command = db.CreateCommand()) 
    { 
     foreach (Record record in recordsToAdd) 
     { 
      // Set the query command text 
      command.CommandText = @"INSERT INTO SMDGROUP_STPRODMASTER (PRODCODE, TOTFREE, TOTPHYS, ITEMTYPE, PRODESC) VALUES ('@PRODCODE', '@TOTFREE', '@TOTPHYS', '@ITEMTYPE', '@PRODESC')"; 

      SqlParameter param1 = new SqlParameter("@CURSTAT", record.curstat); 
      SqlParameter param2 = new SqlParameter("@ITEMDESC", record.itemdesc); 
      SqlParameter param3 = new SqlParameter("@PRODCODE", record.prodcode); 
      SqlParameter param4 = new SqlParameter("@TOTFREE", record.totfree); 
      SqlParameter param5 = new SqlParameter("@TOTPHYS", record.totphys); 
      SqlParameter param6 = new SqlParameter("@ITEMTYPE", record.itemtype); 
      SqlParameter param7 = new SqlParameter("@PRODESC", record.proddesc); 

      command.Parameters.Add(param1); 
      command.Parameters.Add(param2); 
      command.Parameters.Add(param3); 
      command.Parameters.Add(param4); 
      command.Parameters.Add(param5); 
      command.Parameters.Add(param6); 
      command.Parameters.Add(param7); 

      // Execute the query 
      command.ExecuteNonQuery(); 
     } 
     return true; 
    } 
} 

Oto moja klasa rekord:

class Record 
{ 
    public string curstat { get; set; } 
    public string itemtype { get; set; } 
    public string itemdesc { get; set; } 
    public string prodcode { get; set; } 
    public string proddesc { get; set; } 
    public string totfree { get; set; } 
    public string totphys { get; set; } 
} 

Już od patrząc na kod, mam wrażenie, że istnieje krótszy sposób osiągnięcia tego.

Ale po drugie, nie jestem nawet pewien, czy zrobiłem to poprawnie, że wartości @PARAMETER są wymieniane.

Jeśli wyświetlana jest zawartość command, nadal wyświetla ciąg zapytania z parametrami @.

Również ja dostaję ten błąd na command.ExecuteNonQuery():

String lub dane binarne zostaną obcięte.

Oświadczenie zostało wypowiedziane.

Więc moje pytania to:

  • Czy istnieje krótsza droga do ustawiania wielu parametrów i dodać do zapytania?
  • Co może być przyczyną błędu?
+1

Jaka jest definicja Twojego typu rekordu? –

+2

Błąd jest prawdopodobnie spowodowany próbą wstawienia danych do kolumny, która nie jest wystarczająco duża, aby ją zapisać. Na przykład próba przechowania 'abcdef' w' varchar (5) 'spowodowałaby ten błąd. –

+0

Dodałem teraz klasę do pytania, dziękuję! – Luke

Odpowiedz

15

masz większy konstruktora:

command.Parameters.Add(
    "@CategoryName", SqlDbType.VarChar, 80).Value = "toasters"; 
+1

Zaletą tego podejścia jest obcinanie danych do określonego rozmiaru i typu danych. –

+2

Wadą takiego podejścia jest to, że spowoduje to dyskretne uszkodzenie danych bez ostrzeżenia. Nie zgadzam się z podejściem przyjętym przez Microsoft. To naprawdę powinno rzucić wyjątek, a nie dyskretnie skrócić dane. –

6

stosując metodę AddWithValue uczyni kod nieco krótszy:

command.Parameters.AddWithValue("@CURSTAT", record.curstat); 
//... 
+2

Powinieneś sprawdzić [Czy możemy przestać używać AddWithValue() już?] (Http://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/) i przestań używać '.AddWithValue()' - może to prowadzić do nieoczekiwanych i zaskakujących rezultatów ... –

1

W odniesieniu do błędu, to jest problem obcięcia tj długość twojego parametru jest dłuższa niż to, co może pomieścić twoja kolumna. Aby rozwiązać ten problem, podaj dokładniejsze informacje o przekazywaniu parametrów, np. new SqlParameter("@MyParameter", SqlDbType.VarChar, 30).

Osobiście uważam, że nie ma w tym nic złego w tym, jak obecnie dodajesz parametry, które można odczytać i wykonuje to zadanie. Jeśli jednak chcesz zmniejszyć liczbę linii kodu w swojej funkcji, możesz skorzystać z sugestii @Royi lub spakować parametr dodając inną metodę.

+0

Właściwie odpowiedź Tima jest bardziej poprawna. Ten wyjątek nie dotyczy rozmiaru parametru, ale wielkości kolumny. –

+0

@BrandonMoore - Jeśli czytasz moją odpowiedź, wyraźnie stwierdzam, że "twoja kolumna oczekuje mniej znaków niż to, co podaje twój parametr", to znaczy dane parametrów przepełniają rozmiar kolumny. Jest to ta sama odpowiedź sformułowana inaczej - zaktualizowałem ją, by było jeszcze bardziej jasne. – James

+0

Wystarczająco fair. Skupiłem się na części: "Aby obejść ten problem, powinieneś być bardziej konkretny przy przekazywaniu parametrów". –

2

Najprawdopodobniej oznacza to umieszczenie zbyt wielu znaków w jednym z pól VARCHAR. To znaczy, jeśli twoja kolumna PRODDESC jest VARCHAR (50), a ciąg, który próbujesz wstawić, ma 70 znaków, zobaczysz ten błąd.

Inni zajmowali się alternatywnymi sposobami wykonywania parametrów, dzięki czemu można zmniejszyć linie kodu.

3

Robię to trochę inaczej.

Mam zarówno metody rozszerzenie i statycznej metody do tworzenia SqlParameters.

public static SqlParameter ToParam(this object v,string name){ 
return new SqlParameter(name,v); 
} 

Potem zrobić coś takiego:

var p = new List<SqlParameter>(); 
p.Add(record.curstat.ToParam("@curstat")); 
p.Add(record.itemdesc.ToParam("@itemdesc")); 
//etc... 

command.Parameters.AddRange(p.ToList()); 
1

krótszy składni, można użyć AddRange metodę klasy SqlParameterCollection. Oznacza to:

command.Parameters.AddRange(new [] { 
    new SqlParameter(...), 
    new SqlParameter(...), 
    new SqlParameter(...) }); 

Błąd, który otrzymujesz, wskazuje, że wartość ciągu nie pasuje do kolumny lub parametru tabeli i jest obcięta. Powinieneś sprawdzić długość kolumny w porównaniu do wprowadzanych danych lub określić długość parametrów przy użyciu innego przeciążenia konstruktora SqlParameter.

0

Jeśli chciał wykorzystać następujące klasy:

Class MyParam 
{ 
    public string name {get;set;} 
    public object value {get;set;} 
} 

następnie można mieć listę zwane myParams i zrobić:

foreach(var p in myParams) command.Parameters.AddWithValue(p.name, p.value); 

Najwyraźniej trzeba połączyć parametry i wartości jakoś i tam nie ma tego. Ale jeśli zrobisz to w klasie takiej jak ta, kod, który faktycznie wykonuje akcję, ma tylko jedną linię.

0

myślę, że wiadomość

String or binary data would be truncated. 

The statement has been terminated. 

pochodzi z błędu w tekście komendy: w zapytaniu SQL parametry, nawet jeśli są struny, nie muszą być podane.

Wymień polecenia z tego

command.CommandText = @"INSERT INTO SMDGROUP_STPRODMASTER 
     (PRODCODE, TOTFREE, TOTPHYS, ITEMTYPE, PRODESC) 
     VALUES (@PRODCODE, @TOTFREE, @TOTPHYS, @ITEMTYPE, @PRODESC)"; 

Aby skrócić kod myślę można dodać gdzieś (na przykład w swojej klasie zapisów lub klasy pomocnika) metoda, która tworzy tablicę parametru z rejestru obiekt, a następnie wywołaj funkcję AddRange. Powinno to sprawić, że ta funkcja będzie czystsza i możesz jej użyć również w innej części twojego kodu.

Powiązane problemy