4

I am using dapper and I'm trying to use the following tutorial for inserting a list into the database.

https://dapper-tutorial.net/knowledge-base/17150542/how-to-insert-a-csharp-list-to-database-using-dapper-net

I first thought from this example that it meant that @A @B had to be in my class, it was not obvious from the example that they had to be in my class.

public void ExportTOSql()
{
   string connectionString;
   connectionString = System.Configuration.ConfigurationManager.
   ConnectionStrings["Dapper"].ConnectionString.ToString();
     _salesOrders = Program.SageDatabaseHelper.FetchSoPOrdersODBC().OrderByDescending(o => o.OrderDate).ToList();

 using (SqlConnection conn = new SqlConnection(connectionString))
 {
     conn.Open();              
     string processQuery = "INSERT INTO SalesOrders VALUES (@OrderDate, @OrderNumber, @DespatchDate,@AccountReference,@CustomerOrderNumber,@Name,@TotalAmount,@Allocated,@Despatched,@Printed)"; 
     conn.Execute(processQuery, _salesOrders);

}

My Sales Order class is as follows and you can see OrderDate is there.

public class SalesOrder
{
    public DateTime OrderDate;
    public int OrderNumber;
    public byte OrderType;
    public string DespatchDate;
    public string AccountReference;
    public string CustomerOrderNumber;
    public string Name;
    public double TotalAmount;
    public string Allocated;
    public string Despatched;
    public bool Printed;
}

But as you can see from the screenshot, this is the message I got:

enter image description here

Edit 2 OK: I have gotten a step further thanks to help improving my knowledge on this. Now the structure is:

public class SalesOrder
{
    public int OrderNumber { get; set; }
    public DateTime OrderDate { get; set; }   
    public byte OrderType { get; set; }
    public DateTime DespatchDate { get; set; }
    public string AccountReference { get; set; }
    public string CustomerOrderNumber { get; set; }
    public string Name { get; set; }
    public double TotalAmount { get; set; }
    public string Allocated { get; set; }
    public string Despatched { get; set; }
    public bool Printed { get; set; }
}

And my export method is as follows:

public void ExportTOSql()
{
        string connectionString;
        connectionString = System.Configuration.ConfigurationManager.
ConnectionStrings["Dapper"].ConnectionString.ToString();
        _salesOrders = Program.SageDatabaseHelper.FetchSoPOrdersODBC().OrderByDescending(o => o.OrderDate).ToList();
        using (SqlConnection conn = new SqlConnection(connectionString))
        {
            conn.Open();
            string processQuery = "INSERT INTO SalesOrders VALUES ( @OrderNumber,@OrderDate,@OrderType , @DespatchDate,@AccountReference,@CustomerOrderNumber,@Name,@TotalAmount,@Allocated,@Despatched,@Printed)";
            conn.Execute(processQuery, _salesOrders);

}

And my sql table is as follows, but now I am getting the following:

System.Data.SqlClient.SqlException: 'Error converting data type nvarchar to numeric.'

enter image description here

So the issue here is that it still fails sending the data to the SQL table.

Palle Due
  • 5,929
  • 4
  • 17
  • 32
Dave
  • 233
  • 2
  • 12
  • 1
    Can you show your Sales Order class? – stuartd Feb 14 '19 at 14:20
  • @stuartd just did forgot that i didnt add it – Dave Feb 14 '19 at 14:21
  • 1
    .. by the way, that tutorial is a reprint of [this question](https://stackoverflow.com/questions/17150542/how-to-insert-a-c-sharp-list-to-database-using-dapper-net) – stuartd Feb 14 '19 at 14:21
  • Just in passing, you will likely be happier in the long term if you enumerate the column names in your INSERT statement: `INSERT Into MyTable (ColA, ColB) Values (@ColA, @ColB)`. It's not usual that the schema for a table ends up subtly different in the same table in different environment-specific versions of the table (i.e., with time, ALTER TABLE scripts get run in different order on the Dev, QA, and Prod databases for the same table). – Flydog57 Feb 14 '19 at 15:06
  • @Flydog57 I am finding that please see my edit answer above. – Dave Feb 14 '19 at 15:43
  • 1
    Regarding your new error: `Allocated` is a string in your model but a decimal in your table. Make the types compatible and the error should be resolved. – Igor Feb 14 '19 at 15:53

2 Answers2

3

It is because you are using fields and not properties in your model. Try adding {get;set;} to each field to make them properties.

public class SalesOrder
{
    public DateTime OrderDate { get; set; }
    public int OrderNumber { get; set; }
    public byte OrderType { get; set; }
    public string DespatchDate { get; set; }
    public string AccountReference { get; set; }
    public string CustomerOrderNumber { get; set; }
    public string Name { get; set; }
    public double TotalAmount { get; set; }
    public string Allocated { get; set; }
    public string Despatched { get; set; }
    public bool Printed { get; set; }
}

From the documentation you provided:

Note that the MyObject property names A and B match the SQL parameter names @A and @B.

Once you do that @OrderDate can be mapped back to the model's property OrderDate.

Igor
  • 60,821
  • 10
  • 100
  • 175
  • @Dave - seeing as this is a new/different problem the best thing to do would be start a new question. You can copy the new text from this question and then roll back the change after the copy/paste (in history you can rollback any edit). – Igor Feb 14 '19 at 15:48
  • 2
    @Dave - Regarding your new error: `Allocated` is a string in your model but a decimal in your table. Make the types compatible and the error should be resolved. If not or if it requires additional work/thought please consider creating a new question. – Igor Feb 14 '19 at 15:54
1

It is because you are not using query parameterization corretly. Start from the following example:

private static void UpdateDemographics(Int32 customerID,
string demoXml, string connectionString)
{
    string commandText = "UPDATE Sales.Store SET Demographics = @demographics "
        + "WHERE CustomerID = @ID;";

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        SqlCommand command = new SqlCommand(commandText, connection);

        // You have to define the parameters, and give the input which it
        // gets value from. This will be put into the query that the 
        // framework produces
        command.Parameters.Add("@ID", SqlDbType.Int);
        command.Parameters["@ID"].Value = customerID;

        // Use AddWithValue to assign Demographics.
        // SQL Server will implicitly convert strings into XML.
        command.Parameters.AddWithValue("@demographics", demoXml);

        try
        {
            connection.Open();
            Int32 rowsAffected = command.ExecuteNonQuery();
            Console.WriteLine("RowsAffected: {0}", rowsAffected);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

You can read about this topic here

Kristóf Tóth
  • 791
  • 4
  • 19
  • 2
    That's not necessary with Dapper, it can read the properties off the object and automatically assign them. – stuartd Feb 14 '19 at 14:44
  • Yes thats true, but its an alternative if you for example can't produce mathing property names or smth. And ultimately this is what dapper produces in the end so it's easier to undestand this way. – Kristóf Tóth Feb 14 '19 at 15:28