2014-10-20 52 views
0

考慮下面的TESTDB與TestTable的和程序WebMatrix中Database.Query使用自定義的CommandTimeout

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 @[email protected]",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> 

這使Timeout過期錯誤,因爲WebMatrix Database.Query幫助程序修復了默認的30秒CommandTimeout。 有什麼辦法可以將單個查詢的默認值重寫爲5分鐘嗎?

沒有找到解決方案,我根據大量搜索創建了自己的SimpleQuery幫手,並嘗試了一些東西,直到我終於找到了能夠理解和適應的code reference

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; 
     } 
    } 
} 

所以現在用更改網絡的代碼以使用新SimpleQuery幫手,我可以得到幾乎相同的結果,但也有一些問題

@{ 
    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> 

問題1-3中被註釋掉第二個使用SimpleQuery助手的web代碼。這些我可以解決,但我仍然在努力的是爲什麼沒有檢測到數字和日期值的NULL檢查。

我將不勝感激幫助正確檢測這些,所以我可以避免使用Double.Parse或DateTime.Parse後來的錯誤。我也很感謝SimpleQuery helper的任何常規指針/改進,或者你看到的任何其他指針。

在此先感謝。

回答

0

您可以嘗試切換到使用Dapper。它具有與WebMatrix.Data非常相似的語法,可以返回結果爲IEnumerable<dynamic>或根據需要強類型化,並且可以在每個查詢的基礎上覆蓋命令超時。

https://github.com/StackExchange/dapper-dot-net

+0

謝謝您的參考。我會仔細看看的。在我解決問題後,我會接受答案。 – cusman 2014-10-21 14:01:53

0

使用下面用我SimpleQuery助手時,適用於檢測空或的String.Empty,因爲從我的助手的值時,轉換成的ToString()來了爲的String.Empty而從Database.Query未來,他們回來爲NULL。

@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> 
} 

因此,儘管原因是有區別的或如何使我的SimpleQuery助手更相當於Database.Query這不給我解釋一下,它確實幫我搬過去眼前的問題。

相關問題