Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 创建类的属性并在运行时向其投影_C#_Entity Framework_Linq_Select_Datatable - Fatal编程技术网

C# 创建类的属性并在运行时向其投影

C# 创建类的属性并在运行时向其投影,c#,entity-framework,linq,select,datatable,C#,Entity Framework,Linq,Select,Datatable,我在运行时从存储过程中的DataTable中获取列。代码如下所示: var parkDataTable = new DataTable("tmp"); ... SqlCommand cmd = new SqlCommand("FooStoredProcedure", db.Database.Connection as SqlConnection, transaction.UnderlyingTransaction as SqlTransaction); cmd.CommandType

我在运行时从存储过程中的DataTable中获取列。代码如下所示:

var parkDataTable = new DataTable("tmp");
...
SqlCommand cmd = new SqlCommand("FooStoredProcedure", db.Database.Connection as 
    SqlConnection, transaction.UnderlyingTransaction as SqlTransaction);
cmd.CommandType = CommandType.StoredProcedure;    
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
parkDataTable.Load(dr);
有趣的是,通过在列名中添加日期,我的列可以有不同的名称。例如,我有一个列名2017-09-01_FactPark,那么下次可以是2017-10-01_FactPark。请参见以下带有列的图像:

我可以在运行时知道列名和列的数量

是否可以在运行时创建一个将上述列作为属性的类,并像往常一样将它们投影到这些属性:

public IQueryable<EmployeeDTO> GetEmployees()
{
    return db.Employees
        .Select(employee => new EmployeeDTO
        {
            ID = employee.ID,                    
            FirstName = employee.PriceNumber,
            LastName = employee.PriceDate                                        
        }).AsQueryable();
}
因此,我的目标是创建具有DataTable属性的类,并将DataTable列投影到具有属性的类


是否可以在运行时创建属性,并将DataTable列投影到类的新创建属性

动态构造类形状的一种方法是使用DynamicObject类。您可以创建自己的动态类,该类将设置和获取属性及其值

现在,让我们实现我们的动态类:

using System.Dynamic;

class Dynamo : DynamicObject
{
    private Dictionary<string, object> items = new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return items.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        items[binder.Name] = value;
        return true;
    }

    public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
    {
        string propName = indexes[0] as string;
        items[propName] = value;
        return true;
    }

    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
    {
        string propName = indexes[0] as string;
        return items.TryGetValue(propName, out result);
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return items.Keys;
    }
}
static void Main(string[] args)
{

    var data = new List<dynamic>();
    List<string> cols = default;

    using (var conn = new SqlConnection(connStr))
    {
        conn.Open();
        using (var comm = new SqlCommand("SELECT * FROM dbo.Client", conn))
        {
            using (var reader = comm.ExecuteReader())
            {
                // Get columns names
                cols = Enumerable.Range(0, reader.FieldCount)
                       .Select(i => reader.GetName(i)).ToList();
                while (reader.Read())
                {
                    dynamic obj = new Dynamo();
                    cols.ForEach(c => obj[c] = reader[c]);
                    data.Add(obj);
                }
            }
        }
    }


    /* OUTPUT DATA */

    // To get columns names, you can:
    // 1) use ready "cols" variable
    // 2) use "GetDynamicMemberNames()" on first object:
    //    IEnumerable<string> cols = data[0].GetDynamicMemberNames();
    foreach (var obj in data)
    {
        Console.WriteLine(String.Join(", ", cols.Select(c => $"{c} = {obj[c]}")));
    }

    // Output:
    // ClientId = 1, ClientName = Client1
    // ClientId = 2, ClientName = Client2

}
应用程序的逻辑如下:您可以从SqlDataReader获取列的名称,并使用它们在动态对象上进行设置

下面是使用SqlDataReader和我们的动态类的一个可能的变体:

using System.Dynamic;

class Dynamo : DynamicObject
{
    private Dictionary<string, object> items = new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return items.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        items[binder.Name] = value;
        return true;
    }

    public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
    {
        string propName = indexes[0] as string;
        items[propName] = value;
        return true;
    }

    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
    {
        string propName = indexes[0] as string;
        return items.TryGetValue(propName, out result);
    }

    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return items.Keys;
    }
}
static void Main(string[] args)
{

    var data = new List<dynamic>();
    List<string> cols = default;

    using (var conn = new SqlConnection(connStr))
    {
        conn.Open();
        using (var comm = new SqlCommand("SELECT * FROM dbo.Client", conn))
        {
            using (var reader = comm.ExecuteReader())
            {
                // Get columns names
                cols = Enumerable.Range(0, reader.FieldCount)
                       .Select(i => reader.GetName(i)).ToList();
                while (reader.Read())
                {
                    dynamic obj = new Dynamo();
                    cols.ForEach(c => obj[c] = reader[c]);
                    data.Add(obj);
                }
            }
        }
    }


    /* OUTPUT DATA */

    // To get columns names, you can:
    // 1) use ready "cols" variable
    // 2) use "GetDynamicMemberNames()" on first object:
    //    IEnumerable<string> cols = data[0].GetDynamicMemberNames();
    foreach (var obj in data)
    {
        Console.WriteLine(String.Join(", ", cols.Select(c => $"{c} = {obj[c]}")));
    }

    // Output:
    // ClientId = 1, ClientName = Client1
    // ClientId = 2, ClientName = Client2

}

2017-0901_FactPark,2017-10-01_FactPark。。。有人需要正常化…你不能或不允许@JohnyL列名是由存储过程的SELECT语句创建的,我不允许更改此SELECT语句。我认为您试图将动态列强制转换为静态定义的属性是错误的。为什么不将动态字段公开为键/值集合?这将允许您枚举和查找值,而无需重新编译代码。也就是说,存储过程可以更改,但您的代码不需要更改。您计划如何使用查询结果?当然你不能在代码中使用这个类,因为属性是在运行时生成的,没有机会进行测试,但是我相信你:@JohnyL nice,两个月前我还在想同样的问题,但是没有发布它。这可以用ExpandoObjects完成吗?@Yollo Expando不允许你使用Indexer,也就是说,你不能这样写:exp[Age]=100。错误为:无法将带[]的索引应用于ExpandooObject类型的表达式。