الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

مشكلة في فتح الإتصال أكثر من مرة في نفس الوقت ويزداد عدد الكونيكشن

بدأه Altokally في 14 ديسمبر 2013 · 4 رد · 755 مشاهدة · في ASP.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم الأعضاء الكرام
أرجو المساعدة في توصيف المشكلة عند إستخدام الكود ادناه لحصر عدد الإتصال على قاعدة البيانات يظهر عدد كبير جداً ويزداد بالرغم من أن هذه المشكلة تبدأ عند فتح الموقع من قبل اثنين فقط أو ثلاثة أشخاص بيوصل عدد الكونيكشن مرات لل 800 كونيكشن ، الكود موضح أدناه

الكود المستخدم في السيكوال سيرفر

SELECT 
    DB_NAME(dbid) as DBName, 
    COUNT(dbid) as NumberOfConnections,
    loginame as LoginName
FROM
    sys.sysprocesses
WHERE 
    dbid > 0
GROUP BY 
    dbid, loginame

الكود المستخدم في الكلاس لفتح الإتصال وغلقه ومثال على إستخدام فنكشن
 

public class DBClass
{
    SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString());
    string sqlComm = "";
    SqlDataReader newRdr;
    SqlCommand newComm = new SqlCommand();


    public _DBClass()
{
        if (conn.State != ConnectionState.Open)
        {
            conn.Open();
        }
    }


    public void Closeconn()
    {
        conn.Close();
    }
}

مثال على الفنكشن

   
public int Add_News(News newNews)
    {
        try
             {
            sqlComm = "insert into Table_News(Title_AR, Summary_AR, Details_AR, Title_EN, Summary_EN, Details_EN, Thumb_URL, Statues) values(@Title_AR, @Summary_AR, @Details_AR, @Title_EN, @Summary_EN, @Details_EN, @Thumb_URL, @Statues)";
            newComm = new SqlCommand(sqlComm, conn);
            newComm.Parameters.Add("@Title_AR", SqlDbType.NVarChar).Value = newNews.Title_AR;
            newComm.Parameters.Add("@Summary_AR", SqlDbType.NVarChar).Value = newNews.Summary_AR;
            newComm.Parameters.Add("@Details_AR", SqlDbType.NVarChar).Value = newNews.Details_AR;
            newComm.Parameters.Add("@Title_EN", SqlDbType.NVarChar).Value = newNews.Title_EN;
            newComm.Parameters.Add("@Summary_EN", SqlDbType.NVarChar).Value = newNews.Summary_EN;
            newComm.Parameters.Add("@Details_EN", SqlDbType.NVarChar).Value = newNews.Details_EN;
            newComm.Parameters.Add("@Thumb_URL", SqlDbType.NVarChar).Value = newNews.Thumb_URL;
            newComm.Parameters.Add("@Statues", SqlDbType.Int).Value = newNews.Statues;
            newComm.ExecuteNonQuery();
            newComm.Dispose();


            sqlComm = "select News_ID from Table_News ORDER BY News_ID DESC";
            newComm = new SqlCommand(sqlComm, conn);
            newRdr = newComm.ExecuteReader();
            if (newRdr.Read())
                newNews.News_ID = (int)newRdr[0];
            newComm.Dispose();
            newRdr.Close();


            return newNews.News_ID;
        }
        catch (Exception)
        { throw; }
    }
#2

السلام عليكم ...

الـــ sysprocesses جدول خاص  بكامل الــ Sql Server Instance   ... يعني لو انت على استضافة مشتركة , سيعطيك معلومات من كافة المشتركين معك على نفس الــ Sql Server .. ,  لاحظ القيم الكبيرة . و تذكر ان القاعدة master  هي مشتركة ... ركز على القيم الخاصة بالقاعدة خاصتك .

سيكوال سيرفر يزودنا بــ dynamic management views  على الجدول (sys.sysprocesses)  للحصول على معلومات مفيدة عما يجري داخل سيكوال سيرفر .. و هي dm_exec_connections و dm_exec_sessions و dm_exec_requests .

سيكوال سيرفر يعطيك معلومات عن الــ Sessions  و الــ connections  و الــ requests لديه ...

انت عندما تتصل على سيكوال سيرفر , يقوك بإنشاء جلسة Session  لك و تحصل على رقمها من خلال :  

select @@SPID

للحصول على الــ Connections  قم بتشغيل : 

SELECT * FROM sys.dm_exec_connections

أما الــ sessions  فــ : 

SELECT * FROM sys.dm_exec_sessions

حاولت العودة لمرجع معتمد  لمعرفة العلاقة بين الــ Session  و الــ connectios  , فوجدت أن أفضل أجابة هي : 

اقتباس

 

The connection is the physical communication channel between SQL Server and the application: the TCP socket, the named pipe, the shared memory region. The session in SQL Server corresponds to the Wikipedia definition of a session: a semi-permanent container of state for an information exchange. In other words the sessions stores settings like cache of your login information, current transaction isolation level, session level SET values etc etc.

Normally there is one session on each connection, but there could be multiple session on a single connection (Multiple Active Result Sets, MARS) and there are sessions that have no connection (SSB activated procedures, system sessions). There are also connections w/o sessions, namely connections used for non-TDS purposes,

المرجع (what-is-the-difference-between-a-connection-and-a-session) رابط .

باختصار بشكل عام  أنت لديك session واحد لكل connection  .. (قد يكون غير ذلك كما هو مذكور في النص الانجليزي ) .

ما يفيدنا هو الفيو المسمى (sys.dm_exec_requests) الذي يعطينا الطلبات التفصيلية التي تتم داخل سيكوال سيرفر .. و لكن لكي تحصل الطلبات التي تتم داخل قاعدة معينة نستخدم :  

select command , * from sys.dm_exec_requests where database_id = DB_ID('DB04')

أنا وضعت الحقل command  في البداية لانه اهم حقل و هو يمثل اسم العملية التي تتم ..

يمكنك ربط الــ sessions  بالــ connections  بالــ requests  للحصول على معلومات تفصيلية : 

SELECT
S.login_name
, S.login_time
, BS.login_name
, BS.login_time
, R.session_id
, R.start_time
, R.command
, R.status
, R.cpu_time
, R.reads
, R.writes
, R.logical_reads
, R.blocking_session_id
, R.database_id
, DB_NAME(R.database_id) as database_name
, C.connect_time
, C.net_transport
, C.protocol_type
, C.client_net_address
FROM sys.dm_exec_requests R
INNER JOIN sys.dm_exec_sessions S on R.session_id = S.session_id
INNER JOIN sys.dm_exec_connections C on R.connection_id = C.connection_id
LEFT JOIN sys.dm_exec_sessions BS on R.blocking_session_id = BS.session_id

رابط .

 

شئ آخر .. طريقتك في إدراج البيانات ترهق السيرفر ... و الأفضل استخدام الطريقة التي تقوم بجلب لك الــ Identity  فورا مع تنفيذ الاستعلام : 


				this.myCommand = new SqlCommand();
				this.myCommand.Connection = DBManager.GetInstance().GetConnection();
				this.myCommand.Transaction = DBTransaction.GetInstance().GetTransaction;
				this.myCommand.CommandType = System.Data.CommandType.Text;
				this.myCommand.CommandText = @"INSERT INTO Account
																	(accNo,accName, accParentNo, accParentName)
												VALUES     (@accNo,@accName, @accParentNo, @accParentName) ; SELECT SCOPE_IDENTITY() ";
																
				myCommand.Parameters.Add(new SqlParameter("@accNo", System.Data.SqlDbType.Int, 4, "accNo"));
				//////
				
				
				myCommand.Parameters["@accNo"].Value = account.accNo ;
				/////
						
				account.id = System.Convert.ToInt32(myCommand.ExecuteScalar());

تم تعديل هذه المشاركة بواسطة حسام الشامي في 14 ديسمبر 2013 في 19:42

1

لا إله إلا الله ... محمد رسول الله

لو كانت مشاركتي مفيدة و تريد تشجيعي على المزيد من العطاء , فضلا قم بتقييم المشاركة

المعرًف القديم : houssam11350_11350

من مواضيعي : ArabGenCode : مولد كود و إجراءات مخزنة و واجهات لجداول سيكوال سيرفر

#3

اخي الكريم حسام،،،

أشكرك على ردك الوافي، ومن الواضح أن خبرتك متقدمة جداً، لكن لي تعلق على نقطتين وهما:

اقتباس
1- الـــ sysprocesses جدول خاص  بكامل الــ Sql Server Instance   ... يعني لو انت على استضافة مشتركة , سيعطيك معلومات من كافة المشتركين معك على نفس الــ Sql Server .. ,  لاحظ القيم الكبيرة . و تذكر ان القاعدة master  هي مشتركة ... ركز على القيم الخاصة بالقاعدة خاصتك .

 

في المرفقات تبين عدد الكونيكشن لكل قاعدة موجود على السيرفر وأعتقد أن الإستضافة غير مشتركة 
المشكلة أن العدد الواضح 501 في نفس الوقت اللي متصل فيه أنا فقط على الموقع وليس أكثر 
connection_count.jpg
 

اقتباس
2 - شئ آخر .. طريقتك في إدراج البيانات ترهق السيرفر ... و الأفضل استخدام الطريقة التي تقوم بجلب لك الــ Identity  فورا مع تنفيذ الاستعلام : 

 

أرجو التوضيح أكثر أو تزودني برواط لإستخدام الطريقة الأمثل.


ربنا يباركك ويعوض تعبك خير.




 

#4

السلام عليكم ... 

بارك الله بك أخي ...

محتويات الـــ Sysprocesses  ليست  كونكشن كما تعتبرها ..   بل هي كما يوحي اسمها "عمليات داخل النظام" .. أي هي العمليات الداخلية في سيكوال سيرفر ... ما هي العمليات الداخية في النظام ؟؟؟

صديقي .. أنت عندما تقوم بعملية إدراج لسجل واحد في جدول ما ... هي بالنسبة لك عملية واحدة .. و لكن سيكوال سيرفر يترجم هذه العملية الواحدة إلى عدة عمليات داخلية منها (دون ترتيب)  .

- كتابة البيانات للديسك (Lazy Write)

- كتابة سجل في الــ Log  لإمكانية التراجع لاحقا (LOG WRITER) .

 - Monitor Lock  

- CkeckPoint  (أحيانا) .

- ..... الخ

إذا الــ SysProcesses هي عمليات ناتجة عن الاستعلامات و عمليات أخرى يقوم بها النظام على القاعدة ..

الحقل cmd في الجدول sysprocesses  يعطيك اسم العملية ..

العمليات قد لا تكون في الوقت الحالي فمنها ما هو قديم ....

ملاحظة :

يتم حذف السجلات من sysprocesses  الخاصة بقاعدة ما ,  عندما تقوم بعمل deattach  لها .. لذلك جرب مثلا : 

use master;
EXEC sp_detach_db @dbname = N'DB04';
GO
SELECT DB_name(dbid) AS DBName, cmd ,last_batch ,   * FROM sys.sysprocesses where DB_name(dbid) = 'DB04'
GO
EXEC sp_attach_db @dbname = N'DB04', 
    @filename1 = N'd:\sqldata\DB04.mdf', 
    @filename2 = N'd:\sqldata\DB04_log.ldf';
GO
use DB04;
insert into Employee values('E1' , 'Manager' , 3000 , getdate() , 1)
SELECT DB_name(dbid) AS DBName, cmd ,last_batch ,   * FROM sys.sysprocesses where DB_name(dbid) = 'DB04'

لتحصل على  العمليات التي يقوم بها النظام مقابل عبارة Insert  لسجل واحد ... و لاحظ أنه بعد عمل deattach  للقاعدة , لم يعطي أي عمليات عليها ...

باختصار .. اعمل deattch  للقاعدة , ثم attach  ثم نفذ الاستعلام  : 

SELECT DB_name(dbid) AS DBName, cmd ,last_batch ,   * FROM sys.sysprocesses where DB_name(dbid) = 'DB04'

لنرى العمليات على القاعدة خاصتك ... .

ملاحظة : من sql server management studio  نقرة يمينة على اسم السيرفر ثم Activity Monitor   ...كي تراقب السيرفر زمنيا ..

بالنسبة لطريقتك في الحصول على الــ (News_ID) للسجل الجديد الذي فأنت تقوم بجلب كل البيانات من الجدول و هذا ما يرهق السيرفر بقراءة كل بيانات الجدول و نقلها اليك في حين أنك يمكنك الحصول على قيمة الــ (News_ID) من الدالة SCOP_IDENTITY  ببساطة ..

اتبع الطريقة التي وضعتها لك في المشاركة السابقة ..

بالتوفيق ..

تم تعديل هذه المشاركة بواسطة حسام الشامي في 15 ديسمبر 2013 في 13:54

1

لا إله إلا الله ... محمد رسول الله

لو كانت مشاركتي مفيدة و تريد تشجيعي على المزيد من العطاء , فضلا قم بتقييم المشاركة

المعرًف القديم : houssam11350_11350

من مواضيعي : ArabGenCode : مولد كود و إجراءات مخزنة و واجهات لجداول سيكوال سيرفر

#5

to get new id

--sql code
CREATE PROCEDURE dbo.spAdd
    @val1 int,
    @val2 nvarchar(50),
    
    @NewId int OUTPUT
AS
Begin
Begin Transaction
    insert into dbo.Table_1 (Col1,col2) values (@val1,@val2)
    set @NewId=@@identity
if @@ERROR = 0
    commit
else
begin
    raiserror('عفوا حدث خطأ الرجاء اعادة المحاولة',14,1)
    rollback
end
end
---------------
--c# code
 SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString1"].ConnectionString);
 
        try
        {
            con.Open();
        SqlCommand com = new SqlCommand("dbo.spAdd", con);
        com.CommandType = CommandType.StoredProcedure;
        com.Parameters.Add("val1", SqlDbType.Int).Value = val1.ToString();
        com.Parameters.Add("val2", SqlDbType.NVarChar, 50).Value = val2.ToString();
       
        
SqlParameter pvNewId = new SqlParameter();
pvNewId.ParameterName = "@NewId";
pvNewId.DbType = DbType.Int32;
pvNewId.Direction = ParameterDirection.Output;
com.Parameters.Add(pvNewId);

int sqlRows = com.ExecuteNonQuery();

    if (sqlRows > 0)
         MessageBox.Show("New Id Inserted = "+com.Parameters["@NewId"].Value.ToString());
          }
        catch (Exception ex)
        {
         MessageBox.Show(ex.Message);
        }
  finally
        {
            con.Close();
        }

look this link

http://stackoverflow.com/questions/10905782/using-stored-procedure-output-parameters-in-c-sharp

تم تعديل هذه المشاركة بواسطة KARIMSOFT في 15 ديسمبر 2013 في 22:41

2

مواضيع مشابهة