2015-03-19 75 views
2

我试图在Dapper查询中使用结构作为参数。它不适合我。但它好像it should workDapper .NET:结构参数化查询问题

一个失败的例子:

struct Simple { public int ID; } 

[TestMethod] 
public void StructParameter() 
{ 
    int result = Db.Query<int>("select [ID] = @ID", new Simple { ID = 123 }).First(); 
    result.Should().Be(123); 
} 

工作的示例:

[TestMethod] 
public void AnonymousParameter() 
{ 
    int result = Db.Query<int>("select [ID] = @ID", new { ID = 123 }).First(); 
    result.Should().Be(123); 
} 

在第一种情况下引发的错误:

System.Data.SqlClient.SqlException: Must declare the scalar variable "@ID". 
Result StackTrace: 
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) 
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) 
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) 
    at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) 
    at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData() 
    at System.Data.SqlClient.SqlDataReader.get_MetaData() 
    at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite) 
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) 
    at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) 
    at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) 
    at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior) 
    at Dapper.SqlMapper.<QueryImpl>d__11`1.MoveNext() in d:\Dev\dapper-dot-net\Dapper NET40\SqlMapper.cs:line 1553 
    at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) 
    at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) 
    at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in d:\Dev\dapper-dot-net\Dapper NET40\SqlMapper.cs:line 1443 
    ... 

我使用小巧精致的版本1.38。


每建议由德克,属性,而不是一个提交作品就好了:

struct Simple { 
    public int ID { get; set; } 
} 
+0

如果您将struct字段更改为属性,它会工作吗?您发布的github链接中的更改基本上只会将IL代码更改为在值类型的情况下使用'call'而不是'callvirt'。但他们仍然称'GetGetMethod'来访问一个属性。 – Dirk 2015-03-19 09:11:55

+0

@Dirk:是的,一个物业有效。谢谢! – discrete 2015-03-19 09:15:39

+0

@discrete您应该将该编辑放入答案中,并将其标记为已解决,以便其他用户可以轻松找到修补程序 – CodingIntrigue 2015-03-19 09:20:02

回答

6

的问题不是由使用结构造成的,它是通过使用领域,而不是性质引起的。

如果您将struct Simple更改为class Simple仍然不起作用,因为参数读取器仅创建IL代码来读取属性。

ID字段更改为属性将解决此问题。

+0

我有一个尖峰来解决它与字段和属性一起工作,但其中有些内容非常错误,我还没有机会去调试它(或者更有可能:重做它)。你完全正确。 – 2015-03-19 09:32:44