C# WebMatrix数据库。使用自定义命令超时进行查询
考虑以下带有TestTable和过程的TestDbC# WebMatrix数据库。使用自定义命令超时进行查询,c#,sql-server,webmatrix,sqldatareader,command-timeout,C#,Sql Server,Webmatrix,Sqldatareader,Command Timeout,考虑以下带有TestTable和过程的TestDb USE TestDb GO --DROP TABLE dbo.TestTable IF NOT EXISTS (SELECT 1 FROM sys.tables WHERE name = 'TestTable') BEGIN CREATE TABLE dbo.TestTable ( RecordId int NOT NULL IDENTITY(1,1) PRIMARY KEY , StringVa
USE TestDb
GO
--DROP TABLE dbo.TestTable
IF NOT EXISTS (SELECT 1 FROM sys.tables WHERE name = 'TestTable')
BEGIN
CREATE TABLE dbo.TestTable
(
RecordId int NOT NULL IDENTITY(1,1) PRIMARY KEY
, StringValue varchar(50) NULL
, DateValue date NULL
, DateTimeValue datetime NULL
, MoneyValue money NULL
, DecimalValue decimal(19,4) NULL
, IntValue int NULL
, BitValue bit NOT NULL
)
INSERT INTO dbo.TestTable
SELECT 'Test', CAST(GETDATE() AS DATE), GETDATE(), 100.15, 100.0015, 100, 1
UNION SELECT NULL, NULL, NULL, NULL, NULL, NULL, 0
END
GO
IF EXISTS (SELECT 1 FROM sys.procedures WHERE name = 'Get_TestTable')
DROP PROCEDURE dbo.Get_TestTable
GO
CREATE PROCEDURE dbo.Get_TestTable (@RecordId int = NULL) AS WAITFOR DELAY '00:00:30'; SELECT * FROM dbo.TestTable WHERE RecordId = ISNULL(@RecordId,RecordId);
GO
EXEC dbo.Get_TestTable @RecordId = NULL
使用WebMatrix内置数据库查询帮助器时,可以执行以下操作:
@{
string errorMessage = String.Empty;
int? RecordId = null;
IEnumerable<dynamic> rowsTestTable = null;
try
{
using (Database db = Database.Open("TestDb"))
{
rowsTestTable = db.Query("EXEC dbo.Get_TestTable @RecordId=@0",RecordId);
}
}
catch (Exception ex)
{
errorMessage = ex.Message;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
@if(errorMessage == String.Empty)
{
<table border="1">
<thead>
<tr>
<th>RecordId</th>
<th>StringValue</th>
<th>DateValue</th>
<th>DateTimeValue</th>
<th>MoneyValue</th>
<th>DecimalValue</th>
<th>IntValue</th>
<th>BitValue</th>
</tr>
</thead>
<tbody>
@foreach(var row in rowsTestTable)
{
<tr>
<td>@row["RecordId"]</td>
<td>@row["StringValue"]</td>
<td>@if(@row["DateValue"] != null){@Html.Raw(String.Format("{0:MM/dd/yyyy}",@row["DateValue"]));}</td>
<td>@if(@row["DateTimeValue"] != null){@Html.Raw(String.Format("{0:MM/dd/yyyy hh:mm:ss.fff tt}",@row["DateTimeValue"]));}</td>
<td>@if(@row["MoneyValue"] != null){@Html.Raw(String.Format("{0:c}",@row["MoneyValue"]));}</td>
<td>@row["DecimalValue"]</td>
<td>@row["IntValue"]</td>
<td>@row["BitValue"]</td>
</tr>
}
</tbody>
</table>
}
<p>@errorMessage</p>
<h4>No Additional Problem - On handling of DateValue</h4>
@try
{
foreach(var row in rowsTestTable)
{
<p>@if(row.DateValue != null){@Html.Raw(DateTime.Parse(row.DateValue.ToString()))}</p>
}
}
catch (Exception ex)
{
<p>@ex.Message</p>
}
<h4>No Additional Problem - On handling of MoneyValue (and other number values)</h4>
@try
{
foreach(var row in rowsTestTable)
{
<p>@if(row.MoneyValue != null){@Html.Raw(Double.Parse(row.MoneyValue.ToString()))}</p>
}
}
catch (Exception ex)
{
<p>@ex.Message</p>
}
</body>
</html>
@{
string errorMessage=string.Empty;
int?RecordId=null;
IEnumerable rowsTestTable=null;
尝试
{
使用(Database db=Database.Open(“TestDb”))
{
rowsTestTable=db.Query(“EXEC dbo.Get_TestTable@RecordId=@0”,RecordId);
}
}
捕获(例外情况除外)
{
errorMessage=ex.Message;
}
}
@if(errorMessage==String.Empty)
{
记录ID
StringValue
日期值
日期时间值
货币价值
小数点
内在价值
比特值
@foreach(rowsTestTable中的var行)
{
@行[“记录ID”]
@行[“StringValue”]
@如果(@row[“DateValue”]!=null){@Html.Raw(String.Format(“{0:MM/dd/yyyy}”,@row[“DateValue”]);}
@如果(@row[“DateTimeValue”]!=null){@Html.Raw(String.Format({0:MM/dd/yyyy hh:MM:ss.fff tt},@row[“DateTimeValue”]);}
@如果(@row[“MoneyValue”]!=null){@Html.Raw(String.Format(“{0:c}”,@row[“MoneyValue”]);}
@行[“小数值”]
@行[“IntValue”]
@行[“位值”]
}
}
@错误信息
没有其他问题-关于DateValue的处理
@试一试
{
foreach(rowsTestTable中的var行)
{
@if(row.DateValue!=null){@Html.Raw(DateTime.Parse(row.DateValue.ToString())}
}
}
捕获(例外情况除外)
{
@例消息
}
无其他问题-处理MoneyValue(和其他数字值)
@试一试
{
foreach(rowsTestTable中的var行)
{
@if(row.MoneyValue!=null){@Html.Raw(Double.Parse(row.MoneyValue.ToString())}
}
}
捕获(例外情况除外)
{
@例消息
}
这会导致超时过期错误,因为WebMatrix数据库.Query helper已修复默认的30秒命令超时有没有办法将单个查询的默认值改写为5分钟左右?
在没有找到解决方案的情况下,我通过大量搜索和尝试创建了自己的SimpleQuery助手,最终找到了一个我能够理解和适应的解决方案
using System.Collections.Generic; // IEnumerable<dynamic>
using System.Data; // IDataRecord
using System.Data.SqlClient; // SqlConnection
using System.Dynamic; // DynamicObject
public class SimpleQuery
{
public static IEnumerable<dynamic> Execute(string connectionString, string commandString, int commandTimeout)
{
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(commandString, connection))
{
command.CommandTimeout = commandTimeout;
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
foreach (IDataRecord record in reader)
{
yield return new DataRecordDynamicWrapper(record);
}
}
connection.Close();
}
}
}
public class DataRecordDynamicWrapper : DynamicObject
{
private IDataRecord _dataRecord;
public DataRecordDynamicWrapper(IDataRecord dataRecord) { _dataRecord = dataRecord; }
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = _dataRecord[binder.Name];
return result != null;
}
}
}
使用System.Collections.Generic;//数不清
使用System.Data;//伊达塔雷科德
使用System.Data.SqlClient;//连接对象
使用System.Dynamic;//动态对象
公共类单纯形
{
公共静态IEnumerable执行(字符串连接字符串、字符串命令字符串、int命令超时)
{
使用(var连接=新的SqlConnection(connectionString))
{
使用(var命令=新的SqlCommand(commandString,connection))
{
command.CommandTimeout=CommandTimeout;
connection.Open();
使用(SqlDataReader=command.ExecuteReader())
{
foreach(读卡器中的IDataRecord记录)
{
收益返回新数据记录DynamicRapper(记录);
}
}
connection.Close();
}
}
}
公共类DataRecordDynamicRapper:DynamicObject
{
私人IDataRecord(数据记录);
公共DataRecordDynamicRapper(IDataRecord dataRecord){u dataRecord=dataRecord;}
公共重写bool TryGetMember(GetMemberBinder绑定器,输出对象结果)
{
结果=_数据记录[binder.Name];
返回结果!=null;
}
}
}
因此,现在通过更改web代码以使用新的SimpleQuery helper,我可以获得几乎相同的结果,但存在一些问题
@{
string errorMessage = String.Empty;
int? RecordId = null;
IEnumerable<dynamic> rowsTestTable = null;
try
{
string commandString = String.Format("dbo.Get_TestTable @RecordId={0}", RecordId == null ? "null" : RecordId.ToString()); // Problem 1: Have to use String.Format to embed the Parameters
rowsTestTable = SimpleQuery.Execute(System.Configuration.ConfigurationManager.ConnectionStrings["TestDb"].ConnectionString,commandString,300);
foreach(var row in rowsTestTable) { break; } // Problem 2: Have to force query execution here, so the error (if any) gets trapped here
}
catch (Exception ex)
{
errorMessage = ex.Message;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
@if(errorMessage == String.Empty)
{
<table border="1">
<thead>
<tr>
<th>RecordId</th>
<th>StringValue</th>
<th>DateValue</th>
<th>DateTimeValue</th>
<th>MoneyValue</th>
<th>DecimalValue</th>
<th>IntValue</th>
<th>BitValue</th>
</tr>
</thead>
<tbody>
@foreach(var row in rowsTestTable)
{
<tr>
@*<td>@row["RecordId"]</td>*@ <!-- Problem 3: Can't reference as row["FieldName"], so if any field names have spaces or other special characters, can't reference -->
<td>@row.RecordId</td>
<td>@row.StringValue</td>
<td>@if(@row.DateValue != null){@Html.Raw(String.Format("{0:MM/dd/yyyy}",@row.DateValue));}</td>
<td>@if(@row.DateTimeValue != null){@Html.Raw(String.Format("{0:MM/dd/yyyy hh:mm:ss.fff tt}",@row.DateTimeValue));}</td>
<td>@if(@row.MoneyValue != null){@Html.Raw(String.Format("{0:c}",@row.MoneyValue));}</td>
<td>@row.DecimalValue</td>
<td>@row.IntValue</td>
<td>@row.BitValue</td>
</tr>
}
</tbody>
</table>
}
<p>@errorMessage</p>
<h4>Additional Problem - Unexpected handling of DateValue</h4>
@try
{
foreach(var row in rowsTestTable)
{
<p>@if(row.DateValue != null){@Html.Raw(DateTime.Parse(row.DateValue.ToString()))}</p>
}
}
catch (Exception ex)
{
<p>@ex.Message</p>
}
<h4>Additional Problem - Unexpected handling of MoneyValue (and other number values)</h4>
@try
{
foreach(var row in rowsTestTable)
{
<p>@if(row.MoneyValue != null){@Html.Raw(Double.Parse(row.MoneyValue.ToString()))}</p>
}
}
catch (Exception ex)
{
<p>@ex.Message</p>
}
</body>
</html>
@{
string errorMessage=string.Empty;
int?RecordId=null;
IEnumerable rowsTestTable=null;
尝试
{
string commandString=string.Format(“dbo.Get_TestTable@RecordId={0}”,RecordId==null?“null”:RecordId.ToString());//问题1:必须使用string.Format嵌入参数
rowsTestTable=SimpleQuery.Execute(System.Configuration.ConfigurationManager.ConnectionString[“TestDb”]。ConnectionString,commandString,300);
foreach(rowsTestTable中的var row){break;}//问题2:必须在此处强制执行查询,因此错误(如果有)会被捕获在此处
}
捕获(例外情况除外)
{
errorMessage=ex.Message;
}
}
@if(errorMessage==String.Empty)
{
记录ID
StringValue
日期值
日期时间值
货币价值
小数点
内在价值
比特值
@foreach(rowsTestTable中的var行)
{
@*@行[“记录ID”]*@
@row.RecordId
@row.StringValue
@如果(@row.DateValue!=null){@Html.Raw(St
@try
{
foreach(var row in rowsTestTable)
{
<p>@if(!String.IsNullOrEmpty(row.DateValue.ToString())){@Html.Raw(DateTime.Parse(row.DateValue.ToString()))}</p>
}
}
catch (Exception ex)
{
<p>@ex.Message</p>
}