Dapper.Netを使用したDALでのデータ呼び出しの例を次に示します。
/// <summary>
/// Handles db connectivity as Dapper assumes an existing connection for all functions
/// Since the app uses three databases, pass in the connection string for the required db.
/// </summary>
/// <returns></returns>
protected static IDbConnection OpenConnection(string connectionStringName)
{
try
{
connection = new SqlConnection(WebConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString);
//connection = SqlMapperUtil.GetOpenConnection(connectionStringName); // if we want to use the Dapper utility methods
//connection = new SqlConnection(connectionString);
connection.Open();
return connection;
}
catch (Exception ex)
{
ErrorLogging.Instance.Fatal(ex); // uses singleton for logging
return null;
}
}
public string GetNickname(int profileID)
{
string nickname = string.Empty;
using (IDbConnection connection = OpenConnection("PrimaryDBConnectionString"))
{
try
{
var sp_nickname = connection.Query<string>("sq_mobile_nickname_get_by_profileid", new { profileID = profileID }, commandType: CommandType.StoredProcedure);
nickname = sp_nickname.First<string>();
}
catch (Exception ex)
{
ErrorLogging.Instance.Fatal(ex);
return null;
}
}
return nickname;
}
私たちが見ている一貫したエラーは次のとおりです。
2012-06-20 11:42:44.8903|致命的|このコマンドに関連付けられた開いているDataReaderがすでにあり、最初に閉じる必要があります。| System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method、SqlCommand command)at System.Data.SqlClient.SqlCommand.ValidateCommand(String method、Boolean async)at System .Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、String method、DbAsyncResult result)at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、String method) Data.SqlClient.SqlCommand.ExecuteReader(CommandBehaviorの動作、
MyApp.DAL.DapperORM.SqlMapper.d_ 131.MoveNext() in C:\Projects\Git\MyApp\MyApp.DAL\MyApp.DAL.MyAppPrimary.Repositories\Dapper\SqlMapper.cs:line 581 at System.Collections.Generic.List
1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable
1 source)at MyApp.DAL.DapperORM.SqlMapper.Query [T](IDbConnection cnn、String sql、Object param、IDbTransaction transaction、Boolean buffered、Nullable1 commandTimeout, Nullable
1 commandType)in C:\ Projects \ Git \ MyApp \ MyApp.DAL \ MyApp.DAL.MyAppPrimary.Repositories \ Dapper \ SqlMapper.cs:line 538 at MyApp.DAL.Repositories.MemberRepository.AddNotificationEntry(NewsfeedNotification NotificationEntry)in C: \ Projects \ Git \ MyApp \ MyApp.DAL \ MyApp.DAL.MyAppPrimary.Repositories \ MemberRepositories \ MemberRepository.cs:line 465 2012-06-20 11:42:45.2491|致命的|リーダーが閉じているときにReadを呼び出そうとしません。 || System.Data.SqlClient.SqlDataReader.ReadInternal(Boolean setTimeout)で
System.Data.SqlClient.SqlDataReader.Read()at MyApp.DAL.DapperORM.SqlMapper.d _131.MoveNext() in C:\Projects\Git\MyApp\MyApp.DAL\MyApp.DAL.MyAppPrimary.Repositories\Dapper\SqlMapper.cs:line 597 at System.Collections.Generic.List
1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable
1 source)at MyApp.DAL.DapperORM.SqlMapper.Query [T](IDbConnection cnn、String sql、Object param、IDbTransaction transaction、Boolean buffered、Nullable1 commandTimeout, Nullable
1 commandType)in C:\ Projects \ Git \ MyApp \ MyApp.DAL \ MyApp.DAL.MyAppPrimary.Repositories \ Dapper \ SqlMapper.cs:line 538atMyApp.DAL。 DapperORM.SqlMapper.Query(IDbConnection cnn、String sql、Object param、IDbTransaction transaction、Boolean buffered、Nullable1 commandTimeout, Nullable
1 commandType)in C:\ Projects \ Git \ MyApp \ MyApp.DAL \ MyApp.DAL.MyAppPrimary.Repositories \ Dapper \ SqlMapper.cs:line 518 at MyApp.DAL.Repositories.MemberRepository.GetBuddies(Int32 profileID)in C: \ Projects \ Git \ MyApp \ MyApp.DAL \ MyApp.DAL.MyAppPrimary.Repositories \ MemberRepositories \ MemberRepository.cs:line 271 2012-06-20 11:43:01.2392|致命的|シーケンスに要素が含まれていません| System.Linq.Enumerable.First [TSource](IEnumerable`1 source)at MyApp.DAL.Repositories.MemberRepository.GetNickname(Int32 profileID)in C:\ Projects \ Git \ MyApp \ MyApp.DAL \ MyApp.DAL.MyAppPrimary .Repositories \ MemberRepositories \ MemberRepository.cs:line 337
最初は、の中に返品がありusing {...}
、ブロックの外に移動しましたusing
が、それでも同じ問題が発生します。
これはトラフィックの多いアプリケーションであるため、テストでは、この問題は実際に公開されるまで実際には発生しませんでした。
Dapperを使用したDataReader管理のために、ここで実行する必要がある他の何かがありますか?
- - - アップデート - - -
以前にこれを投稿する必要がありましたが、今これを追加するだけです。
Dapper.Netの581行目には、次のExecuteReader()
コードが含まれています。
private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType)
{
var identity = new Identity(sql, commandType, cnn, typeof(T), param == null ? null : param.GetType(), null);
var info = GetCacheInfo(identity);
using (var cmd = SetupCommand(cnn, transaction, sql, info.ParamReader, param, commandTimeout, commandType))
{
using (var reader = cmd.ExecuteReader())
{
Func<Func<IDataReader, object>> cacheDeserializer = () =>
{
info.Deserializer = GetDeserializer(typeof(T), reader, 0, -1, false);
SetQueryCache(identity, info);
return info.Deserializer;
};
if (info.Deserializer == null)
{
cacheDeserializer();
}
var deserializer = info.Deserializer;
while (reader.Read())
{
object next;
try
{
next = deserializer(reader);
}
catch (DataException)
{
// give it another shot, in case the underlying schema changed
deserializer = cacheDeserializer();
next = deserializer(reader);
}
yield return (T)next;
}
}
}
...ネストされたusing
コードに表示されますか?yield return (T)next;
while内、ネスト内のコードが原因で問題が発生しているのではないかとusing
思います。
重要なのは、適度な量のトラフィックでは、Dapperは問題なく動作しているように見えるということです。ただし、1秒あたり約1000リクエストのシステムでは、トリップするようです。
これはDapper開発者にとってはFYIであり、彼らがこれを解決できるかどうか疑問に思っていると思います。
(そして、コードでDapperORMという名前を間違えたことに気づきました-それはORMではありません)