我正在调查使用Dapper并在LinqPad中尝试过这个(你需要提供自己的连接字符串并设置一个'Ticket'表来实际运行它):
using ( var conn = new SqlConnection( builder.ToString() ) )
{
conn.Open();
var loadSql =
@"Insert into Ticket(StatusKey, Status, ContactFirstName, ContactPhoneNumber, WorkflowKey )
Values ( @statusKey, @status, @first, @phoneNumber, @key )";
var values = new[]
{
new { statusKey = "O", status = "Open", first = "Bob", phoneNumber = "6855551425", key = "std" },
new { statusKey = "R", status = "Researching", first = "Sue", phoneNumber = "77785552136", key = "exp" },
new { statusKey = "OD", status = "Overdue", first = "Ted", phoneNumber = "6795551496", key = "std" },
new { statusKey = "C", status = "Closed", first = "Mark", phoneNumber = "9945552678", key = "std" }
};
"Rows Added".Dump();
conn.Execute( loadSql, values ).Dump();
"".Dump();
// Using <dynamic> returns same results
var tickets = conn.Query("Select Status, ContactFirstName, ContactPhoneNumber From Ticket").ToList();
"Tickets Found".Dump();
tickets.Count().Dump();
"".Dump();
"Attempt to get first ticket".Dump();
var firstTicket = tickets[0];
firstTicket.Dump();
(firstTicket ?? "first ticket is null").Dump();
"--- End First Ticket Attempt ---".Dump();
"".Dump();
"Access items returned by query".Dump();
tickets.ForEach( ticketObj =>
{
// ticketObj isn't null, but it not there either??
" Try to dump enumerated ticket".Dump();
if(ticketObj == null) " is null".Dump();
ticketObj.Dump();
//ticketObj.GetType().Dump(); // Null ref exception?
" --- End Enumeration Dump ---".Dump();
// Have to cast to dictionary
var ticket = (IDictionary<string,object>)ticketObj;
string.Format(" {0}: {1} at {2}", ticket["Status"], ticket["ContactFirstName"], ticket["ContactPhoneNumber"]).Dump();
"".Dump();
});
"--- End Access Test ---".Dump();
"".Dump();
conn.Execute("Truncate table ticket");
}
我得到了以下结果:
Rows Added
4
Tickets Found
4
Attempt to get first ticket
--- End First Ticket Attempt ---
Access items returned by query
Try to dump enumerated ticket
--- End Enumeration Dump ---
Open: Bob at 6855551425
Try to dump enumerated ticket
--- End Enumeration Dump ---
Researching: Sue at 77785552136
Try to dump enumerated ticket
--- End Enumeration Dump ---
Overdue: Ted at 6795551496
Try to dump enumerated ticket
--- End Enumeration Dump ---
Closed: Mark at 9945552678
--- End Access Test ---
如你所见,以下是奇怪的:
如果我也使用通用的Query <dynamic>版本,结果是一样的。
我认为动态结果应该是Expandos,我可以做类似的事情
ticketObj.Status.Dump();
即查询中的字段将转换为Query返回的每个对象的属性。我错过了什么?这对Dapper的动态特性有何影响?或者LinqPad可能无法使用动态对象?
这里有两个问题。第一个是LINQPad将实现IDynamicMetaObjectProvider
动态对象转换为IDictionary<string,object>
而不首先转向以获得更好的视图。这已针对下一个版本修复。
第二个问题是,调用Dump()
直接在DapperRow
静静地失败,而不是抛出的RuntimeBinderException
人们所期望的(“DapperRow不包含定义‘转储’”)。我认为,这是DapperRow
实现的DapperRow
。
有许多变通方法。首先,正如您所发现的,首先是object
。另一种解决方法是直接调用Dump
扩展方法:
LINQPad.Extensions.Dump (ticketObj);
要么:
LINQPad.Extensions.Dump (ticketObj, "First ticket");
另一个解决方法是调用Console.WriteLine
,LINQPad重定向到Dump
:
Console.WriteLine (ticketObj);
我已经确定这是一个LinqPad问题。由于它使用扩展方法,因此无法真正处理动态类型。但是,如果将动态转换为对象,则可以正常工作。所以,如果你更换
firstTicket.Dump();
同
((object)firstTicket).Dump();
它的工作......有点儿。它显示带有查询列的IDictionary。 LinqPad无法知道动态添加的列是什么。 有关详细信息, 请参阅此答案 。
同样的技术也在枚举中起作用。如果我改变
ticketObj.Dump();
至
((object)ticketObj).Dump();
有用。我也可以访问动态属性,我只需要先抛出它们。
((string)ticketObj.Status).Dump();
.GetType()似乎不适用于动态类型...我不认为他们有一个。请注意这是否正确,但这在普通的VS控制台应用程序中也不起作用。