Заполните несколько объектов из JSON - PullRequest
0 голосов
/ 16 мая 2019

У меня есть этот код:

public class Customer
{
    Int32 id { get; set; } = 0;
    User user1 { get; set; } = null;
    User user2 { get; set; } = null;
}

/* ... */

using (MySqlConnection conn = new MySqlConnection(Costanti.connessione))
{
    conn.Open();
    MySqlCommand m = new MySqlCommand("
SELECT c1.*, u1.*, u2.*
FROM customers as c1
inner join utenti u1 on u1.customer_id = c1.id
inner join utenti u2 on u2.customer_id = c1.id
", conn);

    MySqlDataReader x = m.ExecuteReader();
    DataTable dataTable = new DataTable();
    dataTable.Load(x);
    String json_string = Newtonsoft.Json.JsonConvert.SerializeObject(dataTable);

    List<Customer> lista = new List<Customer>();
    Newtonsoft.Json.JsonConvert.PopulateObject(json_string, lista);
    conn.Close();
}

Как можно сопоставить c1.* полей выбора с общими Customer customer_1, а затем u1.* и u2.* в свойствах customer_1? Newtonsoft.Json.JsonConvert.PopulateObject не позволяет мне сделать это.

Промежуточное звено json_string выглядит так:

[
   {
      "id":1,
      "id_user":8,
      "name":"manuel",
      "id_user1":2,
      "name1":"michael"
   },
   {
      "id":2,
      "id_user":3,
      "name":"friedrich",
      "id_user1":6,
      "name1":"antony"
   }
]

И результатом должен быть список, составленный из:

  • Customer(with id=1), с User1(8,"manuel") и User2(2,"michael");
  • Customer(with id=2), с User1(3,"friedrich") и User2(6,"antony").

1 Ответ

1 голос
/ 17 мая 2019

Основная причина, по которой ваш вызов PopulateObject() не работает, заключается в том, что ваша модель данных c # не соответствует схеме вашего JSON.Если я использую один из инструментов из Как автоматически сгенерировать файл класса C # из строки объекта JSON для автоматической генерации модели данных из вашего JSON, я получу:

public class RootObject
{
    public int id { get; set; }
    public int id_user { get; set; }
    public string name { get; set; }
    public int id_user1 { get; set; }
    public string name1 { get; set; }
}

Это не похоже на ваш Customer класс.

Вторичная причина сбоя PopulateObject() заключается в том, что Json.NET по умолчанию заполнит только public членов - и все они являются личными.

Исправитьдля этого я мог бы предложить полностью пропустить представления DataTable и json_string и создать свой список непосредственно из интерфейса IDataReader, который MySqlDataReader реализует:

var lista = x
    .SelectRows(r =>
        // Extract the row data by name into a flat object
        new
        {
            id = Convert.ToInt32(r["id"], NumberFormatInfo.InvariantInfo),
            id_user = Convert.ToInt32(r["id_user"], NumberFormatInfo.InvariantInfo),
            name = r["name"].ToString(),
            id_user1 = Convert.ToInt32(r["id_user1"], NumberFormatInfo.InvariantInfo),
            name1 = r["name1"].ToString(),
        })
    .Select(r =>
        // Convert the flat object to a `Customer`.
        new Customer
        {
            id = r.id,
            user1 = new User { Id = r.id_user, Name = r.name },
            user2 = new User { Id = r.id_user1, Name = r.name1 },
        })
        .ToList();

Использование метода расширения:

public static class DataReaderExtensions
{
    // Adapted from this answer https://stackoverflow.com/a/1202973
    // To /863766/konvertirovat-stroki-iz-schityvatelya-dannyh-v-tipizirovannye-rezultaty
    // By https://stackoverflow.com/users/3043/joel-coehoorn
    public static IEnumerable<T> SelectRows<T>(this IDataReader reader, Func<IDataRecord, T> select)
    {
        while (reader.Read())
        {
            yield return select(reader);
        }
    }
}

Предполагается, что ваша модель данных Customer теперь выглядит следующим образом:

public class Customer
{
    public Int32 id { get; set; }
    public User user1 { get; set; }
    public User user2 { get; set; }
}

public class User
{
    public Int32 Id { get; set; }
    public string Name { get; set; }
}

Вы также можете объединить SelectRows иSelect вызовы в один метод;Я разделил их для ясности.Пропуск представлений DataTable и JSON должен быть проще и более производительным, чем ваш текущий подход.

Демонстрационная скрипка с использованием считывателя макетов здесь .

...