如何創建一個動態確定的屬性名稱的匿名對象?

anonymous-types c# dapper

給定一個值數組,我想創建一個具有基於這些值的屬性的匿名對象。屬性名稱只是"pN" ,其中N是數組中值的索引。

例如,給定

object[] values = { 123, "foo" };

我想創建一個匿名對象

new { p0 = 123, p1 = "foo" };

我能想到的做到這一點的唯一方法是使用一個switch或者if鏈最多的參數,以支持一個合理的數字,但我想知道如果有一個更優雅的方式來做到這一點:

object[] parameterValues = new object[] { 123, "foo" };
dynamic values = null;

switch (parameterValues.Length)
{
    case 1:
        values = new { p0 = parameterValues[0] };
        break;
    case 2:
        values = new { p0 = parameterValues[0], p1 = parameterValues[1] };      
        break;
    // etc. up to a reasonable # of parameters
}

背景

我有一組現有的方法來對數據庫執行sql語句。這些方法通常採用sql語句的stringparams object[] (如果有的話)。理解是如果查詢使用參數,它們將被命名為@p0, @p1, @p2, etc.

例:

public int ExecuteNonQuery(string commandText, CommandType commandType, params object[] parameterValues) { .... }

這將被稱為:

db.ExecuteNonQuery("insert into MyTable(Col1, Col2) values (@p0, @p1)", CommandType.Text, 123, "foo");

現在我想在這個類中使用Dapper來包裝和公開Dapper的Query<T>方法,並以與現有方法一致的方式進行,例如:

public IEnumerable<T> ExecuteQuery<T>(string commandText, CommandType commandType, params object[] parameterValues) { .... }

但Dapper的Query<T>方法獲取匿名對像中的參數值:

var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid }); 

導致我關於創建匿名對像以將參數傳遞給Dapper的問題。


添加使用的代碼DynamicParameter類由@Paolo特德斯科的要求。

string sql = "select * from Account where Id = @p0 and username = @p1";
dynamic values = new DynamicParameter(123, "test");
var accounts = SqlMapper.Query<Account>(connection, sql, values);

在Dapper的SqlMapper.cs文件的第581行引發異常:

using (var reader = cmd.ExecuteReader())

並且異常是SqlException

必須聲明標量變量“@ p0”。

並檢查cmd.Parameters屬性顯示沒有為該命令配置參數。

熱門答案

你濫用Dapper,你永遠不需要這樣做,而是實現IDynamicParameters或使用特定的極其靈活的DynamicParameters類。

尤其是:

string sql = "select * from Account where Id = @id and username = @name";
var values = new DynamicParameters();
values.Add("id", 1);
values.Add("name", "bob");
var accounts = SqlMapper.Query<Account>(connection, sql, values);

DynamicParameters可以在構造函數中接受匿名類。您可以Concat的DynamicParameters使用AddDynamicParams方法。

此外,對匿名類型沒有嚴格的依賴性。 Dapper將允許混凝土類型作為參數,例如:

class Stuff
{
   public int Thing { get; set; }
}

...

cnn.Execute("select @Thing", new Stuff{Thing = 1});

凱文有一個類似的問題: 尋找一種快速簡便的方法來合併POCO上的所有屬性 - DynamicParameters在這裡完美運行,而不需要魔術箍跳躍。



許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因