我正在调查使用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 ---
如您所见,以下是奇怪的:
如果我使用通用查询&lt; dynamic&gt;,则结果相同版本也是。
我认为动态结果应该是Expandos,我可以做类似
的事情ticketObj.Status.Dump();
即。查询中的字段将转换为Query返回的每个对象的属性。我错过了什么?这对Dapper的动态特性有何影响?或者LinqPad可能无法使用动态对象?
答案 0 :(得分:4)
这里有两个问题。第一个是LINQPad转储动态对象,将IDynamicMetaObjectProvider
明确地实现为IDictionary<string,object>
,而无需先旋转以获得更好的视图。这已经为下一次构建修复了。
第二个问题是,直接在Dump()
上调用DapperRow
会无声地失败,而不会抛出RuntimeBinderException
人所期望的(&#39; DapperRow不包含&的定义) #34;转储&#34;&#39)。我认为,这是DapperRow
的实施过程中的错误。
有许多解决方法。首先,正如您所发现的那样,首先是object
。另一种解决方法是直接调用Dump
扩展方法:
LINQPad.Extensions.Dump (ticketObj);
或:
LINQPad.Extensions.Dump (ticketObj, "First ticket");
另一个解决方法是调用Console.WriteLine
,LINQPad重定向到Dump
:
Console.WriteLine (ticketObj);
答案 1 :(得分:0)
我已经确定这是一个LinqPad问题。由于它使用扩展方法,因此无法真正处理动态类型。但是,如果将动态转换为对象,则可以正常工作。所以如果你替换
firstTicket.Dump();
与
((object)firstTicket).Dump();
它有效......有点儿。它显示带有查询列的IDictionary。 LinqPad无法知道动态添加的列是什么。 See SO this answer了解更多信息。
这种技术在枚举中也有效。如果我改变
ticketObj.Dump();
到
((object)ticketObj).Dump();
它有效。我也可以访问动态属性,我只需要先抛出它们。
((string)ticketObj.Status).Dump();
.GetType()似乎不适用于动态类型...我不认为他们有一个。请注意这是否正确,但这在普通的VS控制台应用程序中也不起作用。