2010-05-24 14 views
5

मैं एएसपी.नेट एमवीसी, सी # और LINQ से SQL में एक सैंडविच ऑर्डरिंग ऐप पर काम कर रहा हूं। ऐप सामग्री के चयन से कई कस्टम-निर्मित सैंडविच बनाने वाले उपयोगकर्ता के चारों ओर घूमता है।LINQ से SQL: समरूपता के साथ समस्या

जब आदेश की पुष्टि करने की बात आती है तो मुझे यह जानने की आवश्यकता होती है कि डीबी को प्रतिबद्ध करने से पहले उपयोगकर्ता के आदेश में सभी सैंडविच को पूरा करने के लिए प्रत्येक घटक का पर्याप्त भाग है क्योंकि यह संभव है कि एक घटक स्टॉक के बाहर हो जाएगा इसे अपनी टोकरी में जोड़कर और आदेश की पुष्टि।

डेटाबेस के बारे में संक्षिप्त:

घटक - ऑर्डर समय
OrderDetail एक आदेश के लिए हैडर तालिका, बस दुकानों - - भाग की संख्या सहित
आदेश स्टोर घटक विवरण एक गोदाम ऑर्डर में प्रत्येक सैंडविच का रिकॉर्ड
ऑर्डर डेंटलइटम - ऑर्डर

में प्रत्येक सैंडविच में प्रत्येक घटक को स्टोर करता है

तो मूल रूप से मैं सोच रहा हूं कि ऑर्डर, ऑर्डरडेंट और ऑर्डर डेंट इटिम में रिकॉर्ड जोड़ने से पहले मैं यह सुनिश्चित करने के लिए सबसे अच्छा तरीका क्या कर सकता हूं कि मैं यह सुनिश्चित कर सकता हूं कि ऑर्डर पूरा किया जा सके।

+0

आपके पास निहित दौड़ की स्थिति है, कोई भी समाधान संभव व्यापार-बंदों के बारे में है जो विभिन्न दृष्टिकोण आपको देते हैं। – Richard

उत्तर

2
try 
    { 
     Begin netTransaction(); 
     If (IsEnoughIngredients()) 
     { 
      1. Build your sandwich 
      2. Add sandwich to data context with a timestamp (or whatever you chose for concurrency checking) 
      3. SubmitChangesToDataContext() 
      4. CommitNetTransaction() 
     } 
    } catch (Exception e) 
    { 
     Rollback netTransaction(); 
     InformUser(); 
    } 
+1

या एक ट्रांज़ेक्शनस्कोप – RobS

+0

vikp का उपयोग करें - चरण 2 में आप कंसुरेंसी नियंत्रण कैसे कार्यान्वित करेंगे? – Gib

+0

इसके अलावा, मैं लेनदेन अलगाव स्तर के अपने चयन से सावधान रहना चाहता हूं। – RobS

0

प्रत्येक बार जब आप सैंडविच स्टोर करते हैं तो आपको Ingredient मात्रा अपडेट करनी चाहिए।

हालांकि, यह आपके उपयोगकर्ताओं को आपके परिवर्तन करने से पहले एक ही घटक का उपयोग करने से रोक देगा (भले ही स्टॉक पर्याप्त है)।

एक स्टेजिंग टेबल का उपयोग करना बेहतर है जो प्रत्येक घटक जोड़े जाने के बाद प्रतिबद्ध होगा। इससे परिवर्तन एक बार में दिखाई देंगे।

जब आप पूरी तरह से अपना ऑर्डर सबमिट करने के लिए तैयार होते हैं, तो रिकॉर्ड केवल स्टेजिंग टेबल से स्थायी में स्थानांतरित हो जाते हैं।

हालांकि, आपको कुछ रिकॉर्डों से निपटने के लिए कुछ ROLLBACK तंत्र को लागू करना चाहिए। उदाहरण के लिए, एक क्रॉन जॉब जो आदेशों पर गतिविधि की निगरानी करेगा और उन लोगों को हटा देगा जो 10 मिनट या उससे भी अधिक के लिए सक्रिय नहीं हैं।

1

दृष्टिकोणों की संख्या जो आप यहां ले सकते हैं लेकिन मैं निम्नलिखित छद्म कोड की तरह कुछ करूंगा। सुरक्षित धारणा है कि आम तौर पर आदेश को पूरा करने के लिए पर्याप्त सामग्री होगी, इसलिए उस धारणा के आसपास लेनदेन नियंत्रण की संरचना करें और दुर्लभ अपवादों से निपटें।

Begin transaction (Isolation = Repeatable Read) 

For Each OrderDetail In Order.OrderDetailCollection 
    For Each OrderDetailItem In OrderDetail.OrderDetailItemCollection 
     Update Ingredient 
     Set Portions = (Portions – OrderDetailItem.Portions) 
     Where Ingredient.ID = OrderDetailItem.IngredientID 
     And (Portions – OrderDetailItems.Portions) >= 0 

     If RecordsAffected != 1 Then 
      Rollback Transaction 
      SufficientStock = false 
      Exit For 
     End If 
    Next 

    If(SufficientStock = false) 
     Exit For 
    End If 
Next 

संपादित करें: आप सब कुछ Linqing से दूर करने के लिए राजी किया जा सकता है, तो एक वैकल्पिक दृष्टिकोण से बचने के लिए दौर ट्रिपिंग नीचे पंक्तियों के साथ कुछ होगा: अद्यतन स्टॉक के स्तर के लिए

Begin transaction 
    Insert Order (return OrderID) 
    Insert OrderDetails 
    Insert OrderDetailItems 

    Execute update stock stored procedure (see below) 
    If (Success) 
     Commit transaction 
    Else 
     Rollback transaction 
    End IF 

कोड प्रक्रिया:

CREATE PROCEDURE dbo.StockLevel_UpdateByOrderID 
(
    @OrderID INT 
    , @Success BIT 
) 

SET NOCOUNT ON 
SET TRANSACTION ISOLATION LEVEL REPEATEABLE READ 

BEGIN TRANSACTION 

DECLARE @IngredientCount INT 

-- Determine number of ingredients in whole order 
SELECT 
    @IngredientCount = COUNT(odi.IngredientID) 
FROM 
    dbo.OrderDetailItem odi 
INNER JOIN 
    dbo.OrderDetail od 
ON od.OrderDetailID = odi.OrderDetailID 
WHERE 
    od.OrderID = 1 
GROUP BY 
    odi.IngredientID  

-- Update stock levels for all ingredients 
UPDATE 
    dbo.Ingredient 
SET 
    Portions = (i.Portions - odi.TotalPortions) 
FROM 
    dbo.Ingredient i 
INNER JOIN 
    (
    SELECT 
     odi.IngredientID 
     , SUM(odi.Portions) AS TotalPortions 
    FROM 
     dbo.OrderDetailItem odi 
    INNER JOIN 
     dbo.OrderDetail od 
    ON od.OrderDetailID = odi.OrderDetailID 
    WHERE 
     od.OrderID = 1 
    GROUP BY 
     odi.IngredientID 
    ) odi 
ON odi.IngredientID = i.IngredientID 
WHERE 
    (i.Portions - odi.TotalPortions) >= 0 

-- Is number of ingredients updated correct? 
IF(@@ROWCOUNT != @IngredientCount) 
BEGIN 
    ROLLBACK TRANSACTION 
    SET @Success = 0 
END 
ELSE 
BEGIN 
    COMMIT TRANSACTION 
    SET @Success = 0 
END 
0

डीबी कोड जानना अच्छा है, लेकिन अगर आप इसकी मदद कर सकते हैं तो डीबी में बंधे जाने के लिए अच्छा नहीं है। मेनू डिस्प्ले देखने के समय वर्तमान सामग्री पर आधारित होना चाहिए, इसलिए ingredieants से बाहर होना दुर्लभ अपवाद होना चाहिए या आपकी सैंडविच की दुकान लंबे समय तक नहीं टिकेगी ताकि यह सुनिश्चित किया जा सके कि सॉफ्टवेयर कितना अच्छा है।

सामग्री अद्यतन के लिए राउंड ट्रिप से कैसे बचें? क्या लिंक घटक तालिका पर किसी प्रकार के बैच डालने का समर्थन करता है? सीएफई