将 Deedle Dataframe 转换为自定义的 C# 列表 Class
Convert a Deedle Dataframe into a C# List of Custom Class
我从外部 API 接收数据作为 Deedle 数据帧。我需要获取这些数据并将其转换为自定义列表 class 以通过 Entity Framework.
插入到数据库中
有人能给我指出正确的方向吗?我以前没有使用过 Deedle,但在寻找提取数据的最佳方法时遇到了麻烦。
我需要填充的自定义对象如下所示:
public class FrameData
{
public string SecurityId { get; set; }
public string FieldName { get; set; }
public DateTime Date { set; get; }
public decimal value { get; set; }
}
谢谢,
尼克
有很多方法可以从 Deedle 框架中获取数据。 Entity Framework 是否允许您使用接口?如果是这样,那么有一个很好的函数 GetRowsAs
可以让你这样做:
// Given a simple Person interface
public interface Person {
int Age { get; }
string Name{ get; }
}
// And a sample data frame with some data
Frame<int, string> df = Frame.FromValues(new[] {
Tuple.Create(1, "Name", (object) "One"),
Tuple.Create(2, "Name", (object) "Two"),
Tuple.Create(1, "Age", (object) 42),
Tuple.Create(2, "Age", (object) 21)
});
// You can get an array of rows using
var rows = df.GetRowsAs<Person>();
如果Entity Framework 无法处理接口,那么很遗憾,此方法将行不通。在这种情况下,您需要类似的东西:
var rows =
df.Rows.Select(row =>
new Person { Name = row.Value.GetAs<string>("Name"),
Age = row.Value.GetAs<int>("Age"))).Observations;
@Tomas Petricek 所说的是一个很好的例子,但是有很多不同的 classes,这可能会成为一个问题。
所以我在这里举了一个例子,如何将它动态转换为特定的class,并使用属性在属性和列的索引之间进行映射。
// Mapp a key to an index
public class IndexAttribute: Attribute(){
public int Index { get; private set; }
public IndexAttribute(int index){
Index = index;
}
}
public class FrameData
{
[IndexAttribute(0)]
public string SecurityId { get; set; }
[IndexAttribute(3)]
public string FieldName { get; set; }
[IndexAttribute(2)]
public DateTime Date { set; get; }
[IndexAttribute(1)]
public decimal value { get; set; }
}
// create a class the convert the frame to class
public static List<T> Convert<T>(this DataTable data) where T: class
{
var list = new List<T>();
foreach(var row in data.Rows){
object item = Activator.CreateInstance(typeof(T));
var props = typeof(T).GetProperties();
foreach(var p in props){
var index = p.GetCustomAttribute<IndexAttribute>()?.Index ?? -1;
if (index< 0)
continue;
if (table.Columns.length > index) // if the index exist
{
var value = row[index]; // get the value.
if (value == null)
continue; // ignore null value
if (prop.PropertyType == typeof(string))
prop.SetValue(item, value.ToString());
if (prop.PropertyType == typeof(DateTime))
prop.SetValue(item, DateTime.Parse(value.ToString()));
// .. now check for decimal, int etc
}
}
list.Add(item);
}
return list;
}
And now all you need is to call the function
List<Person> persons = df.Convert<Person>(); // that all
我从外部 API 接收数据作为 Deedle 数据帧。我需要获取这些数据并将其转换为自定义列表 class 以通过 Entity Framework.
插入到数据库中有人能给我指出正确的方向吗?我以前没有使用过 Deedle,但在寻找提取数据的最佳方法时遇到了麻烦。
我需要填充的自定义对象如下所示:
public class FrameData
{
public string SecurityId { get; set; }
public string FieldName { get; set; }
public DateTime Date { set; get; }
public decimal value { get; set; }
}
谢谢, 尼克
有很多方法可以从 Deedle 框架中获取数据。 Entity Framework 是否允许您使用接口?如果是这样,那么有一个很好的函数 GetRowsAs
可以让你这样做:
// Given a simple Person interface
public interface Person {
int Age { get; }
string Name{ get; }
}
// And a sample data frame with some data
Frame<int, string> df = Frame.FromValues(new[] {
Tuple.Create(1, "Name", (object) "One"),
Tuple.Create(2, "Name", (object) "Two"),
Tuple.Create(1, "Age", (object) 42),
Tuple.Create(2, "Age", (object) 21)
});
// You can get an array of rows using
var rows = df.GetRowsAs<Person>();
如果Entity Framework 无法处理接口,那么很遗憾,此方法将行不通。在这种情况下,您需要类似的东西:
var rows =
df.Rows.Select(row =>
new Person { Name = row.Value.GetAs<string>("Name"),
Age = row.Value.GetAs<int>("Age"))).Observations;
@Tomas Petricek 所说的是一个很好的例子,但是有很多不同的 classes,这可能会成为一个问题。
所以我在这里举了一个例子,如何将它动态转换为特定的class,并使用属性在属性和列的索引之间进行映射。
// Mapp a key to an index
public class IndexAttribute: Attribute(){
public int Index { get; private set; }
public IndexAttribute(int index){
Index = index;
}
}
public class FrameData
{
[IndexAttribute(0)]
public string SecurityId { get; set; }
[IndexAttribute(3)]
public string FieldName { get; set; }
[IndexAttribute(2)]
public DateTime Date { set; get; }
[IndexAttribute(1)]
public decimal value { get; set; }
}
// create a class the convert the frame to class
public static List<T> Convert<T>(this DataTable data) where T: class
{
var list = new List<T>();
foreach(var row in data.Rows){
object item = Activator.CreateInstance(typeof(T));
var props = typeof(T).GetProperties();
foreach(var p in props){
var index = p.GetCustomAttribute<IndexAttribute>()?.Index ?? -1;
if (index< 0)
continue;
if (table.Columns.length > index) // if the index exist
{
var value = row[index]; // get the value.
if (value == null)
continue; // ignore null value
if (prop.PropertyType == typeof(string))
prop.SetValue(item, value.ToString());
if (prop.PropertyType == typeof(DateTime))
prop.SetValue(item, DateTime.Parse(value.ToString()));
// .. now check for decimal, int etc
}
}
list.Add(item);
}
return list;
}
And now all you need is to call the function
List<Person> persons = df.Convert<Person>(); // that all