2013-04-30 3 views
0

우리 환경에서 다음 오류가 발생합니다. IIS가 다시 시작될 때 발생하는 것으로 보이지만 재현하기 위해 세부 사항을 좁히지 않았습니다.SubSonic에서 Query 객체를 생성하는 중 오류 발생

A DataTable named 'PeoplePassword' already belongs to this DataSet. 
at System.Data.DataTableCollection.RegisterName(String name, String tbNamespace) 
at System.Data.DataTableCollection.BaseAdd(DataTable table) 
at System.Data.DataTableCollection.Add(DataTable table) 
at SubSonic.SqlDataProvider.GetTableSchema(String tableName, TableType tableType) 
at SubSonic.DataService.GetSchema(String tableName, String providerName, TableType tableType) 
at SubSonic.DataService.GetTableSchema(String tableName, String providerName) 
at SubSonic.Query..ctor(String tableName) 
at Wad.Elbert.Data.Enrollment.FetchByUserId(Int32 userId) 

는 스택 트레이스를 바탕으로, 나는 쿼리 개체를 만드는 동안 오류가 메서드의 두 번째 줄에 무슨 일이 일어나고 생각합니다. 다른 사람에게이 문제가 발생하면 알려주세요. 감사합니다.

기능에 대한 코드는 다음과 같습니다

 public static List<Enrollment> FetchByUserId(int userId) 
    { 
     List<Enrollment> enrollments = new List<Enrollment>(); 
     SubSonic.Query query = new SubSonic.Query("Enrollment"); 
     query.SelectList = "userid, prompt, response, validationRegex, validationMessage, responseType, enrollmentSource"; 
     query.QueryType = SubSonic.QueryType.Select; 
     query.AddWhere("userId", userId); 
     DataSet dataset = query.ExecuteDataSet(); 
     if (dataset != null && 
      dataset.Tables.Count > 0) 
     { 
      foreach (DataRow dr in dataset.Tables[0].Rows) 
      { 
       enrollments.Add(new Enrollment((int)dr["userId"], dr["prompt"].ToString(), dr["response"].ToString(), dr["validationRegex"] != null ? dr["validationRegex"].ToString() : string.Empty, dr["validationMessage"] != null ? dr["validationMessage"].ToString() : string.Empty, (int)dr["responseType"], (int)dr["enrollmentSource"])); 
      } 
     } 
     return enrollments; 
    } 
+0

대답이 없지만 github에서 최신 2.x 버전을 사용하고 있습니까? –

답변

0

이 스레딩 문제입니다.

Subsonic은 SubSonic.DataService.GetTableSchema(...)의 첫 번째 호출에서 스키마를로드하지만 이는 스레드로부터 안전하지 않습니다.

나를 조금 예를 들어이 그 방법은 모든 드라이브를 미리로드 할 경우라면 사전이
비어있는이 방법에 최초의 호출시에 발생하는 잘 설명

private static Dictionary<string, DriveInfo> drives = new Dictionary<string, DriveInfo>; 

private static DriveInfo GetDrive(string name) 
{ 
    if (drives.Count == 0) 
    { 
     Thread.Sleep(10000); // fake delay 
     foreach(var drive in DriveInfo.GetDrives) 
      drives.Add(drive.Name, drive); 
    } 
    if (drives.ContainsKey(name)) 
     return drives[name]; 
    return null; 
} 

이것을 보여 보자.

모든 호출에 대해 요청 된 드라이브 (또는 널)가 리턴됩니다.

그러나 시작 후 직접 두 번 방법을 실행하면 어떻게됩니까? 그런 다음 두 실행 모두 사전에 드라이브를로드하려고 시도합니다. 드라이브를 추가하는 첫 번째 항목이 두 번째 항목을 얻으면 ArgumentException이 throw됩니다 (요소가 이미 있음).

초기 사전로드 후에 모든 것이 정상적으로 작동합니다.

짧게 짧게 두 가지 선택 사항이 있습니다.

  1. SubSonic.DataService.GetTableSchema(...) 스레드 안전을 위해 아음속 소스를 수정하십시오. http://msdn.microsoft.com/de-de/library/c5kehkcz(v=vs.80).aspx

  2. 요청을 수락하기 전에 "Warmup"아음속. 이를 달성하기위한 기술은 응용 프로그램 설계에 달려 있습니다. ASP.NET의 경우에만 응용 프로그램 수명주기 동안 한 번 실행되는 Application_Start 방법이 http://msdn.microsoft.com/en-us/library/ms178473(v=vs.100).aspx

그래서 당신은 기본적으로 테이블을 초기화하기 위해서 음속을 강제하는 방법에

var count = new SubSonic.Query("Enrollment").GetRecordCount(); 

를 넣을 수 있습니다 스키마 그 자체.

관련 문제