none
急 about ADO.Net !!! RRS feed

  • 问题

  • DataSet dsParameter = new DataSet();
    
    protected void Page_Load(object sender, EventArgs e){
    
          DataSet tmp = GetParamter(123);
    
          List<string> ParameterCategory = new List<string>();
    
          foreach (DataTable dt in tmp .Tables){
    
                if(dt.TableName=="SpecialName"){
    
                      ParameterCategory.Insert(0, dt.TableName);
    
                }else{
    
                      ParameterCategory.Add(dt.TableName);
    
                }
    
                DataRow all = dt.NewRow();
    
                all["defaultValue"] = "不限";
    
                dt.Rows.InsertAt(all, 0);
    
                dt.AcceptChanges();
    
                foreach (DataRow dr in dt.Rows){
    
                      dr["url"] = "kkkkkkkkkkkk"; //更多的操作
    
                }
    
                dt.AcceptChanges();
    
          }
    
          tmp .AcceptChanges();
          dsParameter = tmp;
    parameterRepeater.DataSource = ParameterCategory; parameterRepeater.DataBind(); } protected void parameterRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType== ListItemType.AlternatingItem) { Repeater rpt = e.Item.FindControl("parameter") as Repeater; rpt.DataSource = dsParameter.Tables[e.Item.DataItem.ToString()]; rpt.DataBind(); } }


    从上面的代码很容易看出,我这里是两个Repeater嵌套。内部的Repeater在外部Repeater的ItemDataBound事件中,设置DataSource。

    大家可以在IIS中测试下,小访问量情况下是根本没有什么问题的。

    在大访问量情况下:
    1、ItemDataBound的时候,dsParameter有可能没有值。
    2、ParameterCategory.Insert(0, dt.TableName); 这里有可能会出错。
    3、dt.Rows.InsertAt(all, 0); 这里也有可能会出错。

    --------------------------------------------------------错误信息--------------------------------------------------------------
    异常信息:
        异常类型: ArgumentNullException
        异常消息: 值不能为空。
    参数名: key

    线程信息:
        线程 ID: 22
        线程帐户名: NT AUTHORITY\NETWORK SERVICE
        是否正在模拟: False
        堆栈跟踪:    在 System.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
       在 System.Collections.Generic.Dictionary`2.FindEntry(TKey key)
       在 System.Collections.Generic.Dictionary`2.get_Item(TKey key)
       在 System.Data.DataView.CopyTo(DataRowView[] array, Int32 index)
       在 System.Data.DataView.GetEnumerator()
       在 System.Web.UI.WebControls.Repeater.CreateControlHierarchy(Boolean useDataSource)
       在 System.Web.UI.WebControls.Repeater.OnDataBinding(EventArgs e)
       在 System.Web.UI.WebControls.Repeater.DataBind()
       在 Product.Web.UI.ProductList.parameterRepeater_ItemDataBound(Object sender, RepeaterItemEventArgs e)
       在 System.Web.UI.WebControls.Repeater.OnItemDataBound(RepeaterItemEventArgs e)
       在 System.Web.UI.WebControls.Repeater.CreateItem(Int32 itemIndex, ListItemType itemType, Boolean dataBind, Object dataItem)
       在 System.Web.UI.WebControls.Repeater.CreateControlHierarchy(Boolean useDataSource)
       在 System.Web.UI.WebControls.Repeater.OnDataBinding(EventArgs e)
       在 System.Web.UI.WebControls.Repeater.DataBind()
       在 Product.Web.UI.ProductList.Page_Load(Object sender, EventArgs e)
       在 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
       在 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
       在 System.Web.UI.Control.OnLoad(EventArgs e)
       在 System.Web.UI.Control.LoadRecursive()
       在 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

    --------------------------------------------------------错误信息--------------------------------------------------------------
    异常信息:
        异常类型: InvalidOperationException
        异常消息: DataTable 内部索引已损坏:“5”。

    线程信息:
        线程 ID: 32
        线程帐户名: NT AUTHORITY\NETWORK SERVICE
        是否正在模拟: False
        堆栈跟踪:    在 System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 mainTreeNodeID, Int32 position, Boolean append)
       在 System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 mainTreeNodeID, Int32 position, Boolean append)
       在 System.Data.RBTree`1.Insert(K item)
       在 System.Data.Index.RecordStateChanged(Int32 oldRecord, DataViewRowState oldOldState, DataViewRowState oldNewState, Int32 newRecord, DataViewRowState newOldState, DataViewRowState newNewState)
       在 System.Data.DataTable.RecordStateChanged(Int32 record1, DataViewRowState oldState1, DataViewRowState newState1, Int32 record2, DataViewRowState oldState2, DataViewRowState newState2)
       在 System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Int32 position, Boolean fireEvent, Exception& deferredException)
       在 System.Data.DataTable.SetNewRecord(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Boolean fireEvent)
       在 System.Data.DataRow.SetNewRecord(Int32 record)
       在 System.Data.DataRow.EndEdit()
       在 System.Data.DataRow.set_Item(DataColumn column, Object value)
       在 System.Data.DataRow.set_Item(String columnName, Object value)
       在 Product.Web.UI.ProductList.Page_Load(Object sender, EventArgs e)
       在 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
       在 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
       在 System.Web.UI.Control.OnLoad(EventArgs e)
       在 System.Web.UI.Control.LoadRecursive()
       在 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

    --------------------------------------------------------错误信息--------------------------------------------------------------
    异常信息:
        异常类型: NullReferenceException
        异常消息: 未将对象引用设置到对象的实例。

    线程信息:
        线程 ID: 22
        线程帐户名: NT AUTHORITY\NETWORK SERVICE
        是否正在模拟: False
        堆栈跟踪:    在 System.Data.DataTable.RecordStateChanged(Int32 record1, DataViewRowState oldState1, DataViewRowState newState1, Int32 record2, DataViewRowState oldState2, DataViewRowState newState2)
       在 System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Int32 position, Boolean fireEvent, Exception& deferredException)
       在 System.Data.DataTable.SetNewRecord(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Boolean fireEvent)
       在 System.Data.DataRow.SetNewRecord(Int32 record)
       在 System.Data.DataRow.EndEdit()
       在 System.Data.DataRow.set_Item(DataColumn column, Object value)
       在 System.Data.DataRow.set_Item(String columnName, Object value)
       在 Product.Web.UI.ProductList.Page_Load(Object sender, EventArgs e)
       在 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
       在 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
       在 System.Web.UI.Control.OnLoad(EventArgs e)
       在 System.Web.UI.Control.LoadRecursive()
       在 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

    2009年10月4日 2:00

答案

  • 您好,原来您采用了缓存。tmp的作用域只是Page_Load中,锁它效果并不好。并不能保证对共享资源。因为网页在每次被请求时都会生成新的实例,建议采用锁类型来处理。如下:
    我不知道GetParamter的具体实现,建议在GetParamter中对共享资源加锁,采用:
    lock(typeof(类名))
    {

    }
    2009年10月8日 4:58

全部回复

  • 您好,没有看到对dsParameter的赋值,只看到使用。

    建议调试一下,在绑定前先看看数据是否都准备好了。

    在parameterRepeater.DataSource = ParameterCategory;这句设个断点,看看dsParameter里的内容,即即将要绑定的表是否都有数据。
    2009年10月4日 3:07
  • dsParameter = tmp;
    不好意思,漏掉了上面这句代码!

    其实这个代码,在本机上是不会遇到什么问题的。只有在正式环境中,大并发的情况下才会出问题。
    2009年10月4日 5:39
  • 我的建议两点是 第一 大并发量 不建议用dataset 建议用datareader+sql+ 存储过程 可能内存不足造成的
    第二 在dataset不需要使用时候调用dataset.dispose方法
    2009年10月4日 6:59
  • 您好,如果只是读数据,应该无需调用AcceptChanges();方法。

    建议创建单元测试,然后模拟多线程测试一下。在上面我提到的断点中做进一步设置,设置断点的条件。例如当某个表为null时命中。或者使用断言。以便查出原因。
    2009年10月4日 7:36
  • GetParamter(123);
    这个方法是获取一个DataSet数据,这个数据从缓存中获取,如果缓存中没有,自动从数据库中读取出来并缓存。

    使用的时候,就是把缓存的数据拿来,做一些处理之后绑定到Repeater上的。

    错误的地方,其实是.net在维护内部“索引”的时候出的问题。这个有可能和缓存数据内部存储方式有一定的关系。

    另外,我现在是把缓存中数据取出来之后,处理的时候使用了lock,把整个tmp锁定了。发现出现错误的次数少了,但还是有错误。
    2009年10月8日 2:27
  • 您好,原来您采用了缓存。tmp的作用域只是Page_Load中,锁它效果并不好。并不能保证对共享资源。因为网页在每次被请求时都会生成新的实例,建议采用锁类型来处理。如下:
    我不知道GetParamter的具体实现,建议在GetParamter中对共享资源加锁,采用:
    lock(typeof(类名))
    {

    }
    2009年10月8日 4:58
  • public static DataSet GetParamter(int abc)
    {
        Caching cache = new Caching("Paramter"); //参数为“缓存名字”的前缀
        DataSet dsParameter = cache.Get(abc.ToString()) as DataSet;
        if (null == dsParameter)
        {
    	dsParameter = new DataSet();
    	string strSQL = "select xxx from TABLE where abc={0} order by id desc";
    	strSQL = string.Format(strSQL, abc);
    	DataTable dtParameters = SqlHelper.ExecuteDataset(ConnString, CommandType.Text, strSQL, "AllParamtersTable").Tables[0];
    
    	foreach (DataRow dr in dtParameters.Rows)
    	{
    	    int tableIndex = dsParameter.Tables.IndexOf(dr["parametername"].ToString());
    	    if (tableIndex == -1)
    	    {
    		tableIndex = dsParameter.Tables.Count;
    		dsParameter.Tables.Add(dr["parametername"].ToString());
    		dsParameter.Tables[tableIndex].Columns.Add("intValue");
    		dsParameter.Tables[tableIndex].Columns.Add("txtValue");
    	    }
    	    dsParameter.Tables[tableIndex].Rows.Add(new object[] { dr["txt"], dr["int"] });
    	}
    	dsParameter.AcceptChanges();
    	cache.Set(abc.ToString(), dsParameter);
        }
        return dsParameter;
    }
    这是GetParamter的具体实现。

    从上面给的错误代码可以看出来,错误的出现位置似乎不在这个GetParamter内部。
    2009年10月8日 8:21