سؤال

لدي خادم مع هذه الرموز:

procedure TFrmMain.TCPServerExecute(AContext: TIdContext);
begin
      Res := DoRegister(Name,Family,Username,Password);
end;

function TFrmMain.DoRegister(Name,Family,Username,Password:string): bool;
var
  Qry: TSQLQuery;
begin
  Qry := TSQLQuery.Create(nil);
  try
    Qry.SQLConnection := FrmConnect.SQLConnection;
    Qry.SQL.Text :='INSERT INTO `table` ...';
    Qry.ExecSQL();
  finally
    Qry.Free;
  end;
  Result := True;
end;

هل هناك أي مشكلة في الوصول إلى جدول واحد في خيوط مختلفة؟ وما هو الخطير تمامًا في حدث Onexecute؟

شكرا لك على الرد أصدقاء.

إذن ، هل هي طريقة حقيقية لإجراء اتصالات مختلفة لخيوط مختلفة؟

var
  Qry: TSQLQuery;
  SqlCon: TSQLConnection;
Begin
  SqlCon := TSQLConnection.Create(nil);
  Qry := TSQLQuery.Create(nil);
  try
    SqlCon := FrmConnect.SQLConnection;
    Qry.SQLConnection := SqlCon;
  finally
    SqlCon.Free;
    Qry.Free;
  end;
end;
هل كانت مفيدة؟

المحلول

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

SqlCon := TSQLConnection.Create(nil); // create
Qry := TSQLQuery.Create(nil);
try
  //SqlCon := FrmConnect.SQLConnection; // overwrite!!!
  SqlCon.ConnectionString :=  FrmConnect.SQLConnection.ConnectionString;
  SqlCon.Active := true;
  Qry.SQLConnection := SqlCon;
  ...

إذا كنت ترغب في الحصول على تجمع اتصال بيانات ، فهذا أمر صعب للغاية لأن الاتصالات عادة ما تكون خاصة بسلسلة - فأنت بحاجة إلى واحد لكل مؤشر ترابط ولا يمكنك تمريرها بين المواضيع. لذلك ينتهي بك الأمر إلى كتابة الكثير من التعليمات البرمجية لدعم ذلك.

أنا الآن استخدم omnithreadlibrary ولديك طريقة مصنع تُرجع اتصال قاعدة بيانات جديدة. هذا يعطيني تجمع مؤشرات ترابط أقوم بتغذية المهام فيه ، لذلك فإن مهمتي المحددة مرتبطة بخيط موجود عند تنفيذه ، لكن الخيط طويل الأجل إلى حد ما. الكود الذي كان علي أن أكتبه للحصول على هذا صغير جدًا (أنا أستخدم ADO):

type
    // a factory to generate new instances of our thread-specific data
    IThreadPoolData = interface
        ['{14917B01-6613-4737-B87E-0046789D4284}']
        function GetConnection: TADOConnection;
        function GetStoredProc: TADOStoredProc;
    end;

    TThreadPoolData = class(TInterfacedObject, IThreadPoolData)
    strict private
        FADOConnection: TADOConnection;
        FStoredProc: TADOStoredProc; // lazy creation!
    public
        constructor Create(aConnectionString: string); overload;
        destructor Destroy; override;
        function GetConnection: TADOConnection;
        function GetStoredProc: TADOStoredProc;
    end;

// create the connection here so thread creation is slow but using it 
// is (relatively) fast

constructor TThreadPoolData.Create(aConnectionString: string);
begin
    FADOConnection := TADOConnection.Create(nil);
    FADOConnection.LoginPrompt := false;
    FADOConnection.ConnectionString := aConnectionString;
    FADOConnection.ConnectOptions := coAsyncConnect;
    FADOConnection.Connected := true;
end;

destructor TThreadPoolData.Destroy;
begin
    FADOConnection.Connected := false;
    if assigned(FStoredProc) then
        FreeAndNil(FStoredProc);
    FreeAndNil(FADOConnection);
end;

ستحتاج إلى القيام بشيء مماثل إذا كتبت موضوعك أو تجمع الاتصال الخاص بك.

نصائح أخرى

يجب أن يكون لكل مؤشر ترابط الوصول إلى DB اتصاله الخاص ، لا يمكنك مشاركة اتصال DB بين عدة مؤشرات ترابط. يتم استدعاء حدث Onexecute في سياق مؤشر الترابط المقابل للعميل طلب ، لذلك في كل مرة يتم استدعاؤه ، يتم تنفيذها داخل مؤشر ترابط عامل ، ويجب أن يكون لهذا الخيط اتصال DB الخاص به.

إذا كنت لا ترغب في إنشاء اتصال جديد لكل موضوع عامل ؛ يمكن أن يكون أحد الخيارات ، فأنت تكرس مؤشر ترابط واحد لاتصال DB ، وتفويض جميع عمليات DB إلى هذا الموضوع ، على سبيل المثال ، يمكن لخيوطك الأخرى إرسال عبارات SQL الخاصة بهم إلى قائمة انتظار في مؤشر ترابط DB هذا ، ويقوم مؤشر ترابط DB بتنفيذها واحدًا- من قبل واحد باستخدام اتصال ديسيبل واحد. بالطبع إذا اتبعت هذا النهج ، فسيكون كل حمل DB على موضوع واحد ، وإذا كان لديك العديد من عمليات DB ، فإن خيط DB نفسه قد يكون عنق الزجاجة! ما هو أكثر من ذلك ، مع اتخاذ هذا النهج ، سيكون عمليات الإعفاءات غير متزامنة باستثناء استخدام تقنية التزامن كلما طلب كل من مؤشرات الترابط من مؤشر ترابط DB تنفيذ استعلام DB لهم.

لاحظ أيضًا أنه إذا كانت مكونات الوصول إلى DB هي ADO ، فيجب عليك الاتصال بالتواصل مع coinitializion و couninitializial ، لأن وقت تشغيل Delphi يفعل ذلك فقط للموضوع الرئيسي وليس مؤشرات الترابط الأخرى التي يتم إنشاؤها من قبلك.

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

نعم و لا. يمكنك الوصول إلى جدول واحد من مؤشرات ترابط مختلفة ، ولكن تحتاج إلى مثيل TSQLConnection لكل مؤشر ترابط للقيام بذلك بأمان.

تحديث

من الجيد إنشاء اتصال مختلف لكل موضوع. إنه ما تفعله معظم صفحات الويب طوال الوقت أيضًا (البرمجة النصية جانب الخادم باستخدام ASP أو PHP أو ... تعني التنفيذ الأقل حالة وبالتالي لا تنجو الاتصالات إلى الطلب التالي ويجب إعادة تأسيسها).

إذا كنت قلقًا بشأن النفقات العامة ، فيمكنك التفكير في استخدام اتصال واحد كما يوحي VCLDeveloper. سيتعين عليك التأكد من أن أي متغيرات وحقول أعضاء تستخدمها "مؤشر ترابط الاتصال" الذي يتم تغييره بواسطة مؤشرات الترابط الأخرى (على سبيل المثال ، يجب حماية عضو الحقل الذي يستقبل SQL) .

وينطبق الشيء نفسه على تجمع الاتصال كما اقترح Mjustin ، على الرغم من أنه في هذه الحالة ، يجب حماية مجموعة الاتصال من خلال آليات التزامن.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top