我有此代码:
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();
}
如何将select的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")
。答案 0 :(得分:1)
对PopulateObject()
的调用不起作用的主要原因是您的c#数据模型与JSON的模式不匹配。如果我使用 How to auto-generate a C# class file from a JSON object string 中的一种工具从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 https://stackoverflow.com/questions/1202935/convert-rows-from-a-data-reader-into-typed-results
// 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表示应该比您当前的方法更简单,更高效。
使用模型数据读取器here演示小提琴。