Dapper & MS Access - Read funciona, Write does not

ado.net c# dapper ms-access oledb

Pregunta

Comencemos por quitar esto de en medio: estoy atrapado usando un MS Access DB y no puedo cambiarlo.

Esto funciona bien:

using (OleDbConnection conn = ConnectionHelper.GetConnection())
{
  conn.Open();
  var results = conn.Query<string>(
    "select FirstName from Students where LastName = @lastName", 
    new { lastName= "Smith" }
  );
  conn.Close();
}

Esto funciona bien:

using (OleDbConnection conn = ConnectionHelper.GetConnection())
{
  OleDbCommand cmd = new OleDbCommand(
    "update Students set FirstName = @firstName, City = @city where LastName = @lastName", 
    conn
  );
  cmd.Parameters.AddWithValue("firstName", "John");
  cmd.Parameters.AddWithValue("city", "SomeCity");
  cmd.Parameters.AddWithValue("lastName", "Smith");

  conn.Open();
  var result = cmd.ExecuteNonQuery();
  conn.Close();
}

Esto no ... se ejecuta sin error pero establece FirstName como "SomeCity" en el DB y City como "John":

using (OleDbConnection conn = ConnectionHelper.GetConnection())
{
  conn.Open();
  var results = conn.Query<string>(
    "update Students set FirstName = @firstName, City = @city where LastName = @lastName", 
    new { firstName = "John", city = "SomeCity", lastName = "Smith" }
  );
  conn.Close();
}

¿Algunas ideas?

EDITAR A CONTINUACIÓN

Dapper funciona si uso DynamicParameters:

using (OleDbConnection conn = ConnectionHelper.GetConnection())
{
  DynamicParameters parameters = new DynamicParameters();
  parameters.Add("firstName", "John");
  parameters.Add("city", "SomeCity");
  parameters.Add("lastName", "Smith");

  conn.Open();
  var result = conn.Query<string>(
    "update Students set FirstName = @firstName, City = @city where LastName = @lastName",
    parameters
  );
  conn.Close();
}

Respuesta aceptada

Después de excavar, pude encontrar una causa:

A continuación, se muestra un delegado de CreateParamInfoGenerator de SqlMapper de dapper:

    public static Action<IDbCommand, object> CreateParamInfoGenerator(Identity identity)
    {

        // code above here
        IEnumerable<PropertyInfo> props = type.GetProperties().OrderBy(p => p.Name); 

Los accesorios son su param unánime que se vuelve a ordenar por OrderBy (p => p.Name), que mueve la ciudad por adelantado.

new { firstName = "John", city = "SomeCity", lastName = "Smith" }

Props luego se agrega a los parámetros de IDbCommand donde el orden es importante.

Si hago un comentario sobre la cláusula OrderBy (), todo funciona.

También probé DynamicParameters y reordené intencionalmente los atributos para mover la ciudad por adelantado:

        var parameters = new DynamicParameters();
        parameters.Add("city", "SomeCity");
        parameters.Add("firstName", "John");
        parameters.Add("lastName", "Smith");

        var result = dbConnection.Query<string>(
          "update Students set FirstName = @firstName, City = @city where LastName = @lastName",
          parameters
        );

Lo anterior no funcionó tan bien, ¡así que el orden de los atributos es la razón!

Supongo que puede modificar su copia local de SqlMapper por el momento y eliminar OrderBy () y esperar un veredicto oficial de Marc ...

Espero que esto ayude.


Respuesta popular

Tuve un problema similar, lo que hice fue use parameter names like @param1, @param2 lugar de @ name, @ id, @ price para que la orden se mantuviera igual sin tener que modificar el archivo SQLMapper.cs.

Algo como

public void Update(Movie movie)
{
  var sql = "UPDATE myDB.movies set title=@param1, genre=@param2 where ID=@param3";
  db.Execute(sql, new { param1 = movie.Title, param2 = movie.Genre, param3 = movie.ID });
}


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow